diff --git a/gen/adexchangebuyer1d3-cli/Cargo.toml b/gen/adexchangebuyer1d3-cli/Cargo.toml index 91119d1062..010b26b274 100644 --- a/gen/adexchangebuyer1d3-cli/Cargo.toml +++ b/gen/adexchangebuyer1d3-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-adexchangebuyer1d3-cli" -version = "0.1.0+20150326" +version = "0.2.0+20150326" authors = ["Sebastian Thiel "] description = "A complete library to interact with Ad Exchange Buyer (protocol v1.3)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/adexchangebuyer1d3-cli" @@ -17,15 +17,14 @@ keywords = ["adexchangebuyer", "google", "cli"] name = "adexchangebuyer1d3" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-adexchangebuyer1d3] path = "../adexchangebuyer1d3" diff --git a/gen/adexchangebuyer1d3-cli/README.md b/gen/adexchangebuyer1d3-cli/README.md index af5c882bbb..da8f34cb2a 100644 --- a/gen/adexchangebuyer1d3-cli/README.md +++ b/gen/adexchangebuyer1d3-cli/README.md @@ -10,41 +10,49 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *Ad Exchange Buyer* API can be found at the +[official documentation site](https://developers.google.com/ad-exchange/buyer-rest). + # Usage -This documentation was generated from the *Ad Exchange Buyer* API at revision *20150326*. The CLI is at version *0.1.0*. +This documentation was generated from the *Ad Exchange Buyer* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - adexchangebuyer1d3 [options] accounts get [-p ...] [-o ] - adexchangebuyer1d3 [options] accounts list [-p ...] [-o ] - adexchangebuyer1d3 [options] accounts patch -r ... [-p ...] [-o ] - adexchangebuyer1d3 [options] accounts update -r ... [-p ...] [-o ] - adexchangebuyer1d3 [options] billing-info get [-p ...] [-o ] - adexchangebuyer1d3 [options] billing-info list [-p ...] [-o ] - adexchangebuyer1d3 [options] budget get [-p ...] [-o ] - adexchangebuyer1d3 [options] budget patch -r ... [-p ...] [-o ] - adexchangebuyer1d3 [options] budget update -r ... [-p ...] [-o ] - adexchangebuyer1d3 [options] creatives get [-p ...] [-o ] - adexchangebuyer1d3 [options] creatives insert -r ... [-p ...] [-o ] - adexchangebuyer1d3 [options] creatives list [-p ...] [-o ] - adexchangebuyer1d3 [options] direct-deals get [-p ...] [-o ] - adexchangebuyer1d3 [options] direct-deals list [-p ...] [-o ] - adexchangebuyer1d3 [options] performance-report list [-p ...] [-o ] - adexchangebuyer1d3 [options] pretargeting-config delete [-p ...] - adexchangebuyer1d3 [options] pretargeting-config get [-p ...] [-o ] - adexchangebuyer1d3 [options] pretargeting-config insert -r ... [-p ...] [-o ] - adexchangebuyer1d3 [options] pretargeting-config list [-p ...] [-o ] - adexchangebuyer1d3 [options] pretargeting-config patch -r ... [-p ...] [-o ] - adexchangebuyer1d3 [options] pretargeting-config update -r ... [-p ...] [-o ] +adexchangebuyer1d3 [options] + accounts + get [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + billing-info + get [-p ]... [-o ] + list [-p ]... [-o ] + budget + get [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + creatives + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + direct-deals + get [-p ]... [-o ] + list [-p ]... [-o ] + performance-report + list [-p ]... [-o ] + pretargeting-config + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] adexchangebuyer1d3 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/adexchangebuyer1d3-cli/mkdocs.yml b/gen/adexchangebuyer1d3-cli/mkdocs.yml index e1fd1f6136..ffbd316cef 100644 --- a/gen/adexchangebuyer1d3-cli/mkdocs.yml +++ b/gen/adexchangebuyer1d3-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Ad Exchange Buyer v0.1.0+20150326 +site_name: Ad Exchange Buyer v0.2.0+20150326 site_url: http://byron.github.io/google-apis-rs/google-adexchangebuyer1d3-cli site_description: Write integrating applications with bcore diff --git a/gen/adexchangebuyer1d3-cli/src/cmn.rs b/gen/adexchangebuyer1d3-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/adexchangebuyer1d3-cli/src/cmn.rs +++ b/gen/adexchangebuyer1d3-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/adexchangebuyer1d3-cli/src/main.rs b/gen/adexchangebuyer1d3-cli/src/main.rs index 98a6f3da1c..0d88499e70 100644 --- a/gen/adexchangebuyer1d3-cli/src/main.rs +++ b/gen/adexchangebuyer1d3-cli/src/main.rs @@ -2,182 +2,156 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_adexchangebuyer1d3 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - adexchangebuyer1d3 [options] accounts get [-p ...] [-o ] - adexchangebuyer1d3 [options] accounts list [-p ...] [-o ] - adexchangebuyer1d3 [options] accounts patch -r ... [-p ...] [-o ] - adexchangebuyer1d3 [options] accounts update -r ... [-p ...] [-o ] - adexchangebuyer1d3 [options] billing-info get [-p ...] [-o ] - adexchangebuyer1d3 [options] billing-info list [-p ...] [-o ] - adexchangebuyer1d3 [options] budget get [-p ...] [-o ] - adexchangebuyer1d3 [options] budget patch -r ... [-p ...] [-o ] - adexchangebuyer1d3 [options] budget update -r ... [-p ...] [-o ] - adexchangebuyer1d3 [options] creatives get [-p ...] [-o ] - adexchangebuyer1d3 [options] creatives insert -r ... [-p ...] [-o ] - adexchangebuyer1d3 [options] creatives list [-p ...] [-o ] - adexchangebuyer1d3 [options] direct-deals get [-p ...] [-o ] - adexchangebuyer1d3 [options] direct-deals list [-p ...] [-o ] - adexchangebuyer1d3 [options] performance-report list [-p ...] [-o ] - adexchangebuyer1d3 [options] pretargeting-config delete [-p ...] - adexchangebuyer1d3 [options] pretargeting-config get [-p ...] [-o ] - adexchangebuyer1d3 [options] pretargeting-config insert -r ... [-p ...] [-o ] - adexchangebuyer1d3 [options] pretargeting-config list [-p ...] [-o ] - adexchangebuyer1d3 [options] pretargeting-config patch -r ... [-p ...] [-o ] - adexchangebuyer1d3 [options] pretargeting-config update -r ... [-p ...] [-o ] - adexchangebuyer1d3 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::AdExchangeBuyer>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _accounts_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let id: i32 = arg_from_str(&self.opt.arg_id, err, "", "integer"); +impl<'n, 'a> Engine<'n, 'a> { + fn _accounts_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let id: i32 = arg_from_str(&opt.value_of("id").unwrap_or(""), err, "", "integer"); let mut call = self.hub.accounts().get(id); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.accounts().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounts_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Account::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -214,61 +188,66 @@ impl Engine { request.cookie_matching_url = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["cookie-matching-nid", "cookie-matching-url", "id", "kind", "maximum-active-creatives", "maximum-total-qps", "number-active-creatives"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let id: i32 = arg_from_str(&self.opt.arg_id, err, "", "integer"); + let id: i32 = arg_from_str(&opt.value_of("id").unwrap_or(""), err, "", "integer"); let mut call = self.hub.accounts().patch(request, id); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounts_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Account::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -305,200 +284,217 @@ impl Engine { request.cookie_matching_url = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["cookie-matching-nid", "cookie-matching-url", "id", "kind", "maximum-active-creatives", "maximum-total-qps", "number-active-creatives"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let id: i32 = arg_from_str(&self.opt.arg_id, err, "", "integer"); + let id: i32 = arg_from_str(&opt.value_of("id").unwrap_or(""), err, "", "integer"); let mut call = self.hub.accounts().update(request, id); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _billing_info_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let account_id: i32 = arg_from_str(&self.opt.arg_account_id, err, "", "integer"); + fn _billing_info_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let account_id: i32 = arg_from_str(&opt.value_of("account-id").unwrap_or(""), err, "", "integer"); let mut call = self.hub.billing_info().get(account_id); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _billing_info_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _billing_info_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.billing_info().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _budget_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.budget().get(&self.opt.arg_account_id, &self.opt.arg_billing_id); - for parg in self.opt.arg_v.iter() { + fn _budget_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.budget().get(opt.value_of("account-id").unwrap_or(""), opt.value_of("billing-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _budget_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _budget_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Budget::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -532,60 +528,65 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "billing-id", "budget-amount", "currency-code", "id", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.budget().patch(request, &self.opt.arg_account_id, &self.opt.arg_billing_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.budget().patch(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("billing-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _budget_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _budget_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Budget::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -619,107 +620,116 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "billing-id", "budget-amount", "currency-code", "id", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.budget().update(request, &self.opt.arg_account_id, &self.opt.arg_billing_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.budget().update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("billing-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _creatives_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let account_id: i32 = arg_from_str(&self.opt.arg_account_id, err, "", "integer"); - let mut call = self.hub.creatives().get(account_id, &self.opt.arg_buyer_creative_id); - for parg in self.opt.arg_v.iter() { + fn _creatives_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let account_id: i32 = arg_from_str(&opt.value_of("account-id").unwrap_or(""), err, "", "integer"); + let mut call = self.hub.creatives().get(account_id, opt.value_of("buyer-creative-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _creatives_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _creatives_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Creative::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -819,58 +829,63 @@ impl Engine { request.account_id = Some(arg_from_str(value.unwrap_or("-0"), err, "account-id", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["html-snippet", "account-id", "advertiser-id", "advertiser-name", "agency-id", "attribute", "buyer-creative-id", "click-through-url", "date", "filtering-reasons", "height", "kind", "product-categories", "restricted-categories", "sensitive-categories", "status", "vendor-type", "video-url", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.creatives().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _creatives_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _creatives_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.creatives().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "status-filter" => { @@ -888,142 +903,154 @@ impl Engine { "account-id" => { call = call.add_account_id(arg_from_str(value.unwrap_or("-0"), err, "account-id", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["status-filter", "page-token", "buyer-creative-id", "max-results", "account-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _direct_deals_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.direct_deals().get(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _direct_deals_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.direct_deals().get(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _direct_deals_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _direct_deals_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.direct_deals().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _performance_report_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.performance_report().list(&self.opt.arg_account_id, &self.opt.arg_end_date_time, &self.opt.arg_start_date_time); - for parg in self.opt.arg_v.iter() { + fn _performance_report_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.performance_report().list(opt.value_of("account-id").unwrap_or(""), opt.value_of("end-date-time").unwrap_or(""), opt.value_of("start-date-time").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1032,142 +1059,149 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _pretargeting_config_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.pretargeting_config().delete(&self.opt.arg_account_id, &self.opt.arg_config_id); - for parg in self.opt.arg_v.iter() { + fn _pretargeting_config_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.pretargeting_config().delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("config-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _pretargeting_config_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.pretargeting_config().get(&self.opt.arg_account_id, &self.opt.arg_config_id); - for parg in self.opt.arg_v.iter() { + fn _pretargeting_config_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.pretargeting_config().get(opt.value_of("account-id").unwrap_or(""), opt.value_of("config-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _pretargeting_config_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _pretargeting_config_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PretargetingConfig::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1288,106 +1322,115 @@ impl Engine { request.supported_creative_attributes.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["billing-id", "config-id", "config-name", "creative-type", "excluded-content-labels", "excluded-geo-criteria-ids", "excluded-user-lists", "excluded-verticals", "geo-criteria-ids", "is-active", "kind", "languages", "mobile-carriers", "mobile-devices", "mobile-operating-system-versions", "platforms", "supported-creative-attributes", "user-lists", "vendor-types", "verticals"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.pretargeting_config().insert(request, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.pretargeting_config().insert(request, opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _pretargeting_config_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.pretargeting_config().list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _pretargeting_config_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.pretargeting_config().list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _pretargeting_config_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _pretargeting_config_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PretargetingConfig::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1508,60 +1551,65 @@ impl Engine { request.supported_creative_attributes.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["billing-id", "config-id", "config-name", "creative-type", "excluded-content-labels", "excluded-geo-criteria-ids", "excluded-user-lists", "excluded-verticals", "geo-criteria-ids", "is-active", "kind", "languages", "mobile-carriers", "mobile-devices", "mobile-operating-system-versions", "platforms", "supported-creative-attributes", "user-lists", "vendor-types", "verticals"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.pretargeting_config().patch(request, &self.opt.arg_account_id, &self.opt.arg_config_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.pretargeting_config().patch(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("config-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _pretargeting_config_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _pretargeting_config_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PretargetingConfig::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1682,151 +1730,203 @@ impl Engine { request.supported_creative_attributes.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["billing-id", "config-id", "config-name", "creative-type", "excluded-content-labels", "excluded-geo-criteria-ids", "excluded-user-lists", "excluded-verticals", "geo-criteria-ids", "is-active", "kind", "languages", "mobile-carriers", "mobile-devices", "mobile-operating-system-versions", "platforms", "supported-creative-attributes", "user-lists", "vendor-types", "verticals"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.pretargeting_config().update(request, &self.opt.arg_account_id, &self.opt.arg_config_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.pretargeting_config().update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("config-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_accounts { - if self.opt.cmd_get { - call_result = self._accounts_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._accounts_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._accounts_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._accounts_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("accounts", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._accounts_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._accounts_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._accounts_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._accounts_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("accounts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("billing-info", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._billing_info_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._billing_info_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("billing-info".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("budget", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._budget_get(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._budget_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._budget_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("budget".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("creatives", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._creatives_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._creatives_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._creatives_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("creatives".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("direct-deals", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._direct_deals_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._direct_deals_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("direct-deals".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("performance-report", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._performance_report_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("performance-report".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("pretargeting-config", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._pretargeting_config_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._pretargeting_config_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._pretargeting_config_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._pretargeting_config_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._pretargeting_config_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._pretargeting_config_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("pretargeting-config".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_billing_info { - if self.opt.cmd_get { - call_result = self._billing_info_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._billing_info_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_budget { - if self.opt.cmd_get { - call_result = self._budget_get(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._budget_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._budget_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_creatives { - if self.opt.cmd_get { - call_result = self._creatives_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._creatives_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._creatives_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_direct_deals { - if self.opt.cmd_get { - call_result = self._direct_deals_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._direct_deals_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_performance_report { - if self.opt.cmd_list { - call_result = self._performance_report_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_pretargeting_config { - if self.opt.cmd_delete { - call_result = self._pretargeting_config_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._pretargeting_config_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._pretargeting_config_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._pretargeting_config_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._pretargeting_config_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._pretargeting_config_update(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -1839,7 +1939,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1852,7 +1952,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1862,37 +1962,678 @@ impl Engine { let engine = Engine { opt: opt, hub: api::AdExchangeBuyer::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("accounts", "methods: 'get', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one account by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/accounts_get", + vec![ + (Some(r##"id"##), + None, + Some(r##"The account id"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the authenticated user's list of accounts."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/accounts_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing account. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/accounts_patch", + vec![ + (Some(r##"id"##), + None, + Some(r##"The account id"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing account."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/accounts_update", + vec![ + (Some(r##"id"##), + None, + Some(r##"The account id"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("billing-info", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Returns the billing information for one account specified by account ID."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/billing-info_get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The account id."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of billing information for all accounts of the authenticated user."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/billing-info_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("budget", "methods: 'get', 'patch' and 'update'", vec![ + ("get", + Some(r##"Returns the budget information for the adgroup specified by the accountId and billingId."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/budget_get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The account id to get the budget information for."##), + Some(true), + Some(false)), + + (Some(r##"billing-id"##), + None, + Some(r##"The billing id to get the budget information for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates the budget amount for the budget of the adgroup specified by the accountId and billingId, with the budget amount in the request. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/budget_patch", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The account id associated with the budget being updated."##), + Some(true), + Some(false)), + + (Some(r##"billing-id"##), + None, + Some(r##"The billing id associated with the budget being updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates the budget amount for the budget of the adgroup specified by the accountId and billingId, with the budget amount in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/budget_update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The account id associated with the budget being updated."##), + Some(true), + Some(false)), + + (Some(r##"billing-id"##), + None, + Some(r##"The billing id associated with the budget being updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("creatives", "methods: 'get', 'insert' and 'list'", vec![ + ("get", + Some(r##"Gets the status for a single creative. A creative will be available 30-40 minutes after submission."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/creatives_get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The id for the account that will serve this creative."##), + Some(true), + Some(false)), + + (Some(r##"buyer-creative-id"##), + None, + Some(r##"The buyer-specific id for this creative."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Submit a new creative."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/creatives_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of the authenticated user's active creatives. A creative will be available 30-40 minutes after submission."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/creatives_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("direct-deals", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one direct deal by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/direct-deals_get", + vec![ + (Some(r##"id"##), + None, + Some(r##"The direct deal id"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the authenticated user's list of direct deals."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/direct-deals_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("performance-report", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves the authenticated user's list of performance metrics."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/performance-report_list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The account id to get the reports."##), + Some(true), + Some(false)), + + (Some(r##"end-date-time"##), + None, + Some(r##"The end time of the report in ISO 8601 timestamp format using UTC."##), + Some(true), + Some(false)), + + (Some(r##"start-date-time"##), + None, + Some(r##"The start time of the report in ISO 8601 timestamp format using UTC."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("pretargeting-config", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes an existing pretargeting config."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/pretargeting-config_delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The account id to delete the pretargeting config for."##), + Some(true), + Some(false)), + + (Some(r##"config-id"##), + None, + Some(r##"The specific id of the configuration to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets a specific pretargeting configuration"##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/pretargeting-config_get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The account id to get the pretargeting config for."##), + Some(true), + Some(false)), + + (Some(r##"config-id"##), + None, + Some(r##"The specific id of the configuration to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new pretargeting configuration."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/pretargeting-config_insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The account id to insert the pretargeting config for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of the authenticated user's pretargeting configurations."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/pretargeting-config_list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The account id to get the pretargeting configs for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing pretargeting config. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/pretargeting-config_patch", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The account id to update the pretargeting config for."##), + Some(true), + Some(false)), + + (Some(r##"config-id"##), + None, + Some(r##"The specific id of the configuration to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing pretargeting config."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli/pretargeting-config_update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The account id to update the pretargeting config for."##), + Some(true), + Some(false)), + + (Some(r##"config-id"##), + None, + Some(r##"The specific id of the configuration to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("adexchangebuyer1d3") + .author("Sebastian Thiel ") + .version("0.2.0+20150326") + .about("Accesses your bidding-account information, submits creatives for validation, finds available direct deals, and retrieves performance reports.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/adexchangebuyer1d3/Cargo.toml b/gen/adexchangebuyer1d3/Cargo.toml index 3ca84be0e2..b1d5690a80 100644 --- a/gen/adexchangebuyer1d3/Cargo.toml +++ b/gen/adexchangebuyer1d3/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-adexchangebuyer1d3" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel "] description = "A complete library to interact with Ad Exchange Buyer (protocol v1.3)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/adexchangebuyer1d3" @@ -15,9 +15,10 @@ keywords = ["adexchangebuyer", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/adexchangebuyer1d3/README.md b/gen/adexchangebuyer1d3/README.md index 9020cd6ad7..86ca2169f6 100644 --- a/gen/adexchangebuyer1d3/README.md +++ b/gen/adexchangebuyer1d3/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-adexchangebuyer1d3` library allows access to all features of the *Google Ad Exchange Buyer* service. -This documentation was generated from *Ad Exchange Buyer* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *adexchangebuyer:v1.3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *Ad Exchange Buyer* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *adexchangebuyer:v1.3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *Ad Exchange Buyer* *v1d3* API can be found at the [official documentation site](https://developers.google.com/ad-exchange/buyer-rest). @@ -178,7 +178,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_adexchangebuyer1d3/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/adexchangebuyer1d3/src/cmn.rs b/gen/adexchangebuyer1d3/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/adexchangebuyer1d3/src/cmn.rs +++ b/gen/adexchangebuyer1d3/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/adexchangebuyer1d3/src/lib.rs b/gen/adexchangebuyer1d3/src/lib.rs index ad75d34616..d0e4eaa37f 100644 --- a/gen/adexchangebuyer1d3/src/lib.rs +++ b/gen/adexchangebuyer1d3/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *Ad Exchange Buyer* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *adexchangebuyer:v1.3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *Ad Exchange Buyer* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *adexchangebuyer:v1.3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *Ad Exchange Buyer* *v1d3* API can be found at the //! [official documentation site](https://developers.google.com/ad-exchange/buyer-rest). @@ -179,7 +179,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -188,7 +188,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -204,6 +203,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -326,7 +326,7 @@ impl<'a, C, A> AdExchangeBuyer AdExchangeBuyer { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -353,7 +353,7 @@ impl<'a, C, A> AdExchangeBuyer } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1777,7 +1777,7 @@ impl<'a, C, A> BillingInfoGetCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1799,7 +1799,7 @@ impl<'a, C, A> BillingInfoGetCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1990,7 +1990,7 @@ impl<'a, C, A> BillingInfoListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2012,7 +2012,7 @@ impl<'a, C, A> BillingInfoListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2193,7 +2193,7 @@ impl<'a, C, A> DirectDealListCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2215,7 +2215,7 @@ impl<'a, C, A> DirectDealListCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2422,7 +2422,7 @@ impl<'a, C, A> DirectDealGetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2444,7 +2444,7 @@ impl<'a, C, A> DirectDealGetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2614,6 +2614,7 @@ impl<'a, C, A> BudgetPatchCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Budget)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2670,11 +2671,20 @@ impl<'a, C, A> BudgetPatchCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2697,7 +2707,7 @@ impl<'a, C, A> BudgetPatchCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2889,6 +2899,7 @@ impl<'a, C, A> BudgetUpdateCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Budget)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2945,11 +2956,20 @@ impl<'a, C, A> BudgetUpdateCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2972,7 +2992,7 @@ impl<'a, C, A> BudgetUpdateCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3213,7 +3233,7 @@ impl<'a, C, A> BudgetGetCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3235,7 +3255,7 @@ impl<'a, C, A> BudgetGetCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3413,6 +3433,7 @@ impl<'a, C, A> CreativeInsertCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Creative)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3443,11 +3464,20 @@ impl<'a, C, A> CreativeInsertCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3470,7 +3500,7 @@ impl<'a, C, A> CreativeInsertCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3696,7 +3726,7 @@ impl<'a, C, A> CreativeListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3718,7 +3748,7 @@ impl<'a, C, A> CreativeListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3964,7 +3994,7 @@ impl<'a, C, A> CreativeGetCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3986,7 +4016,7 @@ impl<'a, C, A> CreativeGetCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4165,6 +4195,7 @@ impl<'a, C, A> AccountUpdateCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Account)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4220,11 +4251,20 @@ impl<'a, C, A> AccountUpdateCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4247,7 +4287,7 @@ impl<'a, C, A> AccountUpdateCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4428,6 +4468,7 @@ impl<'a, C, A> AccountPatchCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Account)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4483,11 +4524,20 @@ impl<'a, C, A> AccountPatchCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4510,7 +4560,7 @@ impl<'a, C, A> AccountPatchCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4713,7 +4763,7 @@ impl<'a, C, A> AccountListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4735,7 +4785,7 @@ impl<'a, C, A> AccountListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4942,7 +4992,7 @@ impl<'a, C, A> AccountGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4964,7 +5014,7 @@ impl<'a, C, A> AccountGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5171,7 +5221,7 @@ impl<'a, C, A> PerformanceReportListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5193,7 +5243,7 @@ impl<'a, C, A> PerformanceReportListCall<'a, C, A> where C: BorrowMut PretargetingConfigDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5467,7 +5517,7 @@ impl<'a, C, A> PretargetingConfigDeleteCall<'a, C, A> where C: BorrowMut PretargetingConfigPatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, PretargetingConfig)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5693,11 +5744,20 @@ impl<'a, C, A> PretargetingConfigPatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5720,7 +5780,7 @@ impl<'a, C, A> PretargetingConfigPatchCall<'a, C, A> where C: BorrowMut PretargetingConfigGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5983,7 +6043,7 @@ impl<'a, C, A> PretargetingConfigGetCall<'a, C, A> where C: BorrowMut PretargetingConfigInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, PretargetingConfig)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6217,11 +6278,20 @@ impl<'a, C, A> PretargetingConfigInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6244,7 +6314,7 @@ impl<'a, C, A> PretargetingConfigInsertCall<'a, C, A> where C: BorrowMut PretargetingConfigListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6495,7 +6565,7 @@ impl<'a, C, A> PretargetingConfigListCall<'a, C, A> where C: BorrowMut PretargetingConfigUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, PretargetingConfig)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6721,11 +6792,20 @@ impl<'a, C, A> PretargetingConfigUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6748,7 +6828,7 @@ impl<'a, C, A> PretargetingConfigUpdateCall<'a, C, A> where C: BorrowMut"] description = "A complete library to interact with Ad Exchange Seller (protocol v2.0)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/adexchangeseller2-cli" @@ -17,15 +17,14 @@ keywords = ["adexchangeseller", "google", "cli"] name = "adexchangeseller2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-adexchangeseller2] path = "../adexchangeseller2" diff --git a/gen/adexchangeseller2-cli/README.md b/gen/adexchangeseller2-cli/README.md index 92d8de921e..2acab508b4 100644 --- a/gen/adexchangeseller2-cli/README.md +++ b/gen/adexchangeseller2-cli/README.md @@ -10,34 +10,36 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *Ad Exchange Seller* API can be found at the +[official documentation site](https://developers.google.com/ad-exchange/seller-rest/). + # Usage -This documentation was generated from the *Ad Exchange Seller* API at revision *20150326*. The CLI is at version *0.1.0*. +This documentation was generated from the *Ad Exchange Seller* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - adexchangeseller2 [options] accounts adclients-list [-p ...] [-o ] - adexchangeseller2 [options] accounts alerts-list [-p ...] [-o ] - adexchangeseller2 [options] accounts customchannels-get [-p ...] [-o ] - adexchangeseller2 [options] accounts customchannels-list [-p ...] [-o ] - adexchangeseller2 [options] accounts get [-p ...] [-o ] - adexchangeseller2 [options] accounts list [-p ...] [-o ] - adexchangeseller2 [options] accounts metadata-dimensions-list [-p ...] [-o ] - adexchangeseller2 [options] accounts metadata-metrics-list [-p ...] [-o ] - adexchangeseller2 [options] accounts preferreddeals-get [-p ...] [-o ] - adexchangeseller2 [options] accounts preferreddeals-list [-p ...] [-o ] - adexchangeseller2 [options] accounts reports-generate [-p ...] [-o ] - adexchangeseller2 [options] accounts reports-saved-generate [-p ...] [-o ] - adexchangeseller2 [options] accounts reports-saved-list [-p ...] [-o ] - adexchangeseller2 [options] accounts urlchannels-list [-p ...] [-o ] +adexchangeseller2 [options] + accounts + adclients-list [-p ]... [-o ] + alerts-list [-p ]... [-o ] + customchannels-get [-p ]... [-o ] + customchannels-list [-p ]... [-o ] + get [-p ]... [-o ] + list [-p ]... [-o ] + metadata-dimensions-list [-p ]... [-o ] + metadata-metrics-list [-p ]... [-o ] + preferreddeals-get [-p ]... [-o ] + preferreddeals-list [-p ]... [-o ] + reports-generate [-p ]... [-o ] + reports-saved-generate [-p ]... [-o ] + reports-saved-list [-p ]... [-o ] + urlchannels-list [-p ]... [-o ] adexchangeseller2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/adexchangeseller2-cli/mkdocs.yml b/gen/adexchangeseller2-cli/mkdocs.yml index 000951f148..a4785e702a 100644 --- a/gen/adexchangeseller2-cli/mkdocs.yml +++ b/gen/adexchangeseller2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Ad Exchange Seller v0.1.0+20150326 +site_name: Ad Exchange Seller v0.2.0+20150326 site_url: http://byron.github.io/google-apis-rs/google-adexchangeseller2-cli site_description: Write integrating applications with bcore diff --git a/gen/adexchangeseller2-cli/src/cmn.rs b/gen/adexchangeseller2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/adexchangeseller2-cli/src/cmn.rs +++ b/gen/adexchangeseller2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/adexchangeseller2-cli/src/main.rs b/gen/adexchangeseller2-cli/src/main.rs index a626f93310..737c9ddb59 100644 --- a/gen/adexchangeseller2-cli/src/main.rs +++ b/gen/adexchangeseller2-cli/src/main.rs @@ -2,80 +2,53 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_adexchangeseller2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - adexchangeseller2 [options] accounts adclients-list [-p ...] [-o ] - adexchangeseller2 [options] accounts alerts-list [-p ...] [-o ] - adexchangeseller2 [options] accounts customchannels-get [-p ...] [-o ] - adexchangeseller2 [options] accounts customchannels-list [-p ...] [-o ] - adexchangeseller2 [options] accounts get [-p ...] [-o ] - adexchangeseller2 [options] accounts list [-p ...] [-o ] - adexchangeseller2 [options] accounts metadata-dimensions-list [-p ...] [-o ] - adexchangeseller2 [options] accounts metadata-metrics-list [-p ...] [-o ] - adexchangeseller2 [options] accounts preferreddeals-get [-p ...] [-o ] - adexchangeseller2 [options] accounts preferreddeals-list [-p ...] [-o ] - adexchangeseller2 [options] accounts reports-generate [-p ...] [-o ] - adexchangeseller2 [options] accounts reports-saved-generate [-p ...] [-o ] - adexchangeseller2 [options] accounts reports-saved-list [-p ...] [-o ] - adexchangeseller2 [options] accounts urlchannels-list [-p ...] [-o ] - adexchangeseller2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::AdExchangeSeller>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _accounts_adclients_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().adclients_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _accounts_adclients_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().adclients_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -84,145 +57,157 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_alerts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().alerts_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_alerts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().alerts_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "locale" => { call = call.locale(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_customchannels_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().customchannels_get(&self.opt.arg_account_id, &self.opt.arg_ad_client_id, &self.opt.arg_custom_channel_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_customchannels_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().customchannels_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("custom-channel-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_customchannels_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().customchannels_list(&self.opt.arg_account_id, &self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_customchannels_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().customchannels_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -231,96 +216,104 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().get(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().get(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.accounts().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -329,235 +322,255 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_metadata_dimensions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().metadata_dimensions_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_metadata_dimensions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().metadata_dimensions_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_metadata_metrics_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().metadata_metrics_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_metadata_metrics_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().metadata_metrics_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_preferreddeals_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().preferreddeals_get(&self.opt.arg_account_id, &self.opt.arg_deal_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_preferreddeals_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().preferreddeals_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("deal-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_preferreddeals_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().preferreddeals_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_preferreddeals_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().preferreddeals_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_reports_generate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounts_reports_generate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut download_mode = false; - let mut call = self.hub.accounts().reports_generate(&self.opt.arg_account_id, &self.opt.arg_start_date, &self.opt.arg_end_date); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().reports_generate(opt.value_of("account-id").unwrap_or(""), opt.value_of("start-date").unwrap_or(""), opt.value_of("end-date").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -581,57 +594,61 @@ impl Engine { "dimension" => { call = call.add_dimension(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sort", "locale", "metric", "max-results", "filter", "start-index", "dimension"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { if !download_mode { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); } else { io::copy(&mut response, &mut ostream).unwrap(); } - None + Ok(()) } } } } - fn _accounts_reports_saved_generate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().reports_saved_generate(&self.opt.arg_account_id, &self.opt.arg_saved_report_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_reports_saved_generate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().reports_saved_generate(opt.value_of("account-id").unwrap_or(""), opt.value_of("saved-report-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -643,50 +660,54 @@ impl Engine { "locale" => { call = call.locale(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale", "start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_reports_saved_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().reports_saved_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_reports_saved_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().reports_saved_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -695,50 +716,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_urlchannels_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().urlchannels_list(&self.opt.arg_account_id, &self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_urlchannels_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().urlchannels_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -747,99 +772,125 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_accounts { - if self.opt.cmd_adclients_list { - call_result = self._accounts_adclients_list(dry_run, &mut err); - } else if self.opt.cmd_alerts_list { - call_result = self._accounts_alerts_list(dry_run, &mut err); - } else if self.opt.cmd_customchannels_get { - call_result = self._accounts_customchannels_get(dry_run, &mut err); - } else if self.opt.cmd_customchannels_list { - call_result = self._accounts_customchannels_list(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._accounts_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._accounts_list(dry_run, &mut err); - } else if self.opt.cmd_metadata_dimensions_list { - call_result = self._accounts_metadata_dimensions_list(dry_run, &mut err); - } else if self.opt.cmd_metadata_metrics_list { - call_result = self._accounts_metadata_metrics_list(dry_run, &mut err); - } else if self.opt.cmd_preferreddeals_get { - call_result = self._accounts_preferreddeals_get(dry_run, &mut err); - } else if self.opt.cmd_preferreddeals_list { - call_result = self._accounts_preferreddeals_list(dry_run, &mut err); - } else if self.opt.cmd_reports_generate { - call_result = self._accounts_reports_generate(dry_run, &mut err); - } else if self.opt.cmd_reports_saved_generate { - call_result = self._accounts_reports_saved_generate(dry_run, &mut err); - } else if self.opt.cmd_reports_saved_list { - call_result = self._accounts_reports_saved_list(dry_run, &mut err); - } else if self.opt.cmd_urlchannels_list { - call_result = self._accounts_urlchannels_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("accounts", Some(opt)) => { + match opt.subcommand() { + ("adclients-list", Some(opt)) => { + call_result = self._accounts_adclients_list(opt, dry_run, &mut err); + }, + ("alerts-list", Some(opt)) => { + call_result = self._accounts_alerts_list(opt, dry_run, &mut err); + }, + ("customchannels-get", Some(opt)) => { + call_result = self._accounts_customchannels_get(opt, dry_run, &mut err); + }, + ("customchannels-list", Some(opt)) => { + call_result = self._accounts_customchannels_list(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._accounts_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._accounts_list(opt, dry_run, &mut err); + }, + ("metadata-dimensions-list", Some(opt)) => { + call_result = self._accounts_metadata_dimensions_list(opt, dry_run, &mut err); + }, + ("metadata-metrics-list", Some(opt)) => { + call_result = self._accounts_metadata_metrics_list(opt, dry_run, &mut err); + }, + ("preferreddeals-get", Some(opt)) => { + call_result = self._accounts_preferreddeals_get(opt, dry_run, &mut err); + }, + ("preferreddeals-list", Some(opt)) => { + call_result = self._accounts_preferreddeals_list(opt, dry_run, &mut err); + }, + ("reports-generate", Some(opt)) => { + call_result = self._accounts_reports_generate(opt, dry_run, &mut err); + }, + ("reports-saved-generate", Some(opt)) => { + call_result = self._accounts_reports_saved_generate(opt, dry_run, &mut err); + }, + ("reports-saved-list", Some(opt)) => { + call_result = self._accounts_reports_saved_list(opt, dry_run, &mut err); + }, + ("urlchannels-list", Some(opt)) => { + call_result = self._accounts_urlchannels_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("accounts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -852,7 +903,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -865,7 +916,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -875,37 +926,476 @@ impl Engine { let engine = Engine { opt: opt, hub: api::AdExchangeSeller::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("accounts", "methods: 'adclients-list', 'alerts-list', 'customchannels-get', 'customchannels-list', 'get', 'list', 'metadata-dimensions-list', 'metadata-metrics-list', 'preferreddeals-get', 'preferreddeals-list', 'reports-generate', 'reports-saved-generate', 'reports-saved-list' and 'urlchannels-list'", vec![ + ("adclients-list", + Some(r##"List all ad clients in this Ad Exchange account."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/accounts_adclients-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to which the ad client belongs."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("alerts-list", + Some(r##"List the alerts for this Ad Exchange account."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/accounts_alerts-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account owning the alerts."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("customchannels-get", + Some(r##"Get the specified custom channel from the specified ad client."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/accounts_customchannels-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to which the ad client belongs."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client which contains the custom channel."##), + Some(true), + Some(false)), + + (Some(r##"custom-channel-id"##), + None, + Some(r##"Custom channel to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("customchannels-list", + Some(r##"List all custom channels in the specified ad client for this Ad Exchange account."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/accounts_customchannels-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to which the ad client belongs."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to list custom channels."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Get information about the selected Ad Exchange account."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/accounts_get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to get information about. Tip: 'myaccount' is a valid ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all accounts available to this Ad Exchange account."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/accounts_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("metadata-dimensions-list", + Some(r##"List the metadata for the dimensions available to this AdExchange account."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/accounts_metadata-dimensions-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account with visibility to the dimensions."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("metadata-metrics-list", + Some(r##"List the metadata for the metrics available to this AdExchange account."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/accounts_metadata-metrics-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account with visibility to the metrics."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("preferreddeals-get", + Some(r##"Get information about the selected Ad Exchange Preferred Deal."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/accounts_preferreddeals-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account owning the deal."##), + Some(true), + Some(false)), + + (Some(r##"deal-id"##), + None, + Some(r##"Preferred deal to get information about."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("preferreddeals-list", + Some(r##"List the preferred deals for this Ad Exchange account."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/accounts_preferreddeals-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account owning the deals."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reports-generate", + Some(r##"Generate an Ad Exchange report based on the report request sent in the query parameters. Returns the result as JSON; to retrieve output in CSV format specify "alt=csv" as a query parameter."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/accounts_reports-generate", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account which owns the generated report."##), + Some(true), + Some(false)), + + (Some(r##"start-date"##), + None, + Some(r##"Start of the date range to report on in "YYYY-MM-DD" format, inclusive."##), + Some(true), + Some(false)), + + (Some(r##"end-date"##), + None, + Some(r##"End of the date range to report on in "YYYY-MM-DD" format, inclusive."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reports-saved-generate", + Some(r##"Generate an Ad Exchange report based on the saved report ID sent in the query parameters."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/accounts_reports-saved-generate", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account owning the saved report."##), + Some(true), + Some(false)), + + (Some(r##"saved-report-id"##), + None, + Some(r##"The saved report to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reports-saved-list", + Some(r##"List all saved reports in this Ad Exchange account."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/accounts_reports-saved-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account owning the saved reports."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("urlchannels-list", + Some(r##"List all URL channels in the specified ad client for this Ad Exchange account."##), + "Details at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli/accounts_urlchannels-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to which the ad client belongs."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to list URL channels."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("adexchangeseller2") + .author("Sebastian Thiel ") + .version("0.2.0+20150326") + .about("Gives Ad Exchange seller users access to their inventory and the ability to generate reports") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_adexchangeseller2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/adexchangeseller2/Cargo.toml b/gen/adexchangeseller2/Cargo.toml index af525c4d1a..57227462a7 100644 --- a/gen/adexchangeseller2/Cargo.toml +++ b/gen/adexchangeseller2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-adexchangeseller2" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel "] description = "A complete library to interact with Ad Exchange Seller (protocol v2.0)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/adexchangeseller2" @@ -15,9 +15,10 @@ keywords = ["adexchangeseller", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/adexchangeseller2/README.md b/gen/adexchangeseller2/README.md index 816a6f3d73..6b24e4cc79 100644 --- a/gen/adexchangeseller2/README.md +++ b/gen/adexchangeseller2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-adexchangeseller2` library allows access to all features of the *Google Ad Exchange Seller* service. -This documentation was generated from *Ad Exchange Seller* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *adexchangeseller:v2.0* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *Ad Exchange Seller* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *adexchangeseller:v2.0* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *Ad Exchange Seller* *v2* API can be found at the [official documentation site](https://developers.google.com/ad-exchange/seller-rest/). @@ -181,7 +181,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_adexchangeseller2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_adexchangeseller2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/adexchangeseller2/src/cmn.rs b/gen/adexchangeseller2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/adexchangeseller2/src/cmn.rs +++ b/gen/adexchangeseller2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/adexchangeseller2/src/lib.rs b/gen/adexchangeseller2/src/lib.rs index 5ee3654bdb..3e4e9b36d3 100644 --- a/gen/adexchangeseller2/src/lib.rs +++ b/gen/adexchangeseller2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *Ad Exchange Seller* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *adexchangeseller:v2.0* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *Ad Exchange Seller* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *adexchangeseller:v2.0* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *Ad Exchange Seller* *v2* API can be found at the //! [official documentation site](https://developers.google.com/ad-exchange/seller-rest/). @@ -182,7 +182,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -191,7 +191,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -207,6 +206,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -334,7 +334,7 @@ impl<'a, C, A> AdExchangeSeller AdExchangeSeller { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -343,7 +343,7 @@ impl<'a, C, A> AdExchangeSeller } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1269,7 +1269,7 @@ impl<'a, C, A> AccountReportSavedGenerateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1291,7 +1291,7 @@ impl<'a, C, A> AccountReportSavedGenerateCall<'a, C, A> where C: BorrowMut AccountMetadataMetricListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1561,7 +1561,7 @@ impl<'a, C, A> AccountMetadataMetricListCall<'a, C, A> where C: BorrowMut AccountReportGenerateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1876,7 +1876,7 @@ impl<'a, C, A> AccountReportGenerateCall<'a, C, A> where C: BorrowMut AccountUrlchannelListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2200,7 +2200,7 @@ impl<'a, C, A> AccountUrlchannelListCall<'a, C, A> where C: BorrowMut AccountReportSavedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2473,7 +2473,7 @@ impl<'a, C, A> AccountReportSavedListCall<'a, C, A> where C: BorrowMut AccountPreferreddealGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2728,7 +2728,7 @@ impl<'a, C, A> AccountPreferreddealGetCall<'a, C, A> where C: BorrowMut AccountAdclientListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2987,7 +2987,7 @@ impl<'a, C, A> AccountAdclientListCall<'a, C, A> where C: BorrowMut AccountMetadataDimensionListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3240,7 +3240,7 @@ impl<'a, C, A> AccountMetadataDimensionListCall<'a, C, A> where C: BorrowMut AccountCustomchannelGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3483,7 +3483,7 @@ impl<'a, C, A> AccountCustomchannelGetCall<'a, C, A> where C: BorrowMut AccountCustomchannelListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3754,7 +3754,7 @@ impl<'a, C, A> AccountCustomchannelListCall<'a, C, A> where C: BorrowMut AccountListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4001,7 +4001,7 @@ impl<'a, C, A> AccountListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4227,7 +4227,7 @@ impl<'a, C, A> AccountAlertListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4249,7 +4249,7 @@ impl<'a, C, A> AccountAlertListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4473,7 +4473,7 @@ impl<'a, C, A> AccountPreferreddealListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4495,7 +4495,7 @@ impl<'a, C, A> AccountPreferreddealListCall<'a, C, A> where C: BorrowMut AccountGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4734,7 +4734,7 @@ impl<'a, C, A> AccountGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/admin1_directory-cli/Cargo.toml b/gen/admin1_directory-cli/Cargo.toml index 5bb1fd967f..5aec775e75 100644 --- a/gen/admin1_directory-cli/Cargo.toml +++ b/gen/admin1_directory-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-admin1_directory-cli" -version = "0.1.0+20150314" +version = "0.2.0+20150314" authors = ["Sebastian Thiel "] description = "A complete library to interact with directory (protocol directory_v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/admin1_directory-cli" @@ -17,15 +17,14 @@ keywords = ["admin", "google", "cli"] name = "admin1-directory" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-admin1_directory] path = "../admin1_directory" diff --git a/gen/admin1_directory-cli/README.md b/gen/admin1_directory-cli/README.md index d6db5c8114..4153ef4612 100644 --- a/gen/admin1_directory-cli/README.md +++ b/gen/admin1_directory-cli/README.md @@ -10,87 +10,100 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *directory* API can be found at the +[official documentation site](https://developers.google.com/admin-sdk/directory/). + # Usage -This documentation was generated from the *directory* API at revision *20150314*. The CLI is at version *0.1.0*. +This documentation was generated from the *directory* API at revision *20150314*. The CLI is at version *0.2.0*. ```bash - admin1-directory [options] asps delete [-p ...] - admin1-directory [options] asps get [-p ...] [-o ] - admin1-directory [options] asps list [-p ...] [-o ] - admin1-directory [options] channels stop -r ... [-p ...] - admin1-directory [options] chromeosdevices get [-p ...] [-o ] - admin1-directory [options] chromeosdevices list [-p ...] [-o ] - admin1-directory [options] chromeosdevices patch -r ... [-p ...] [-o ] - admin1-directory [options] chromeosdevices update -r ... [-p ...] [-o ] - admin1-directory [options] groups aliases-delete [-p ...] - admin1-directory [options] groups aliases-insert -r ... [-p ...] [-o ] - admin1-directory [options] groups aliases-list [-p ...] [-o ] - admin1-directory [options] groups delete [-p ...] - admin1-directory [options] groups get [-p ...] [-o ] - admin1-directory [options] groups insert -r ... [-p ...] [-o ] - admin1-directory [options] groups list [-p ...] [-o ] - admin1-directory [options] groups patch -r ... [-p ...] [-o ] - admin1-directory [options] groups update -r ... [-p ...] [-o ] - admin1-directory [options] members delete [-p ...] - admin1-directory [options] members get [-p ...] [-o ] - admin1-directory [options] members insert -r ... [-p ...] [-o ] - admin1-directory [options] members list [-p ...] [-o ] - admin1-directory [options] members patch -r ... [-p ...] [-o ] - admin1-directory [options] members update -r ... [-p ...] [-o ] - admin1-directory [options] mobiledevices action -r ... [-p ...] - admin1-directory [options] mobiledevices delete [-p ...] - admin1-directory [options] mobiledevices get [-p ...] [-o ] - admin1-directory [options] mobiledevices list [-p ...] [-o ] - admin1-directory [options] notifications delete [-p ...] - admin1-directory [options] notifications get [-p ...] [-o ] - admin1-directory [options] notifications list [-p ...] [-o ] - admin1-directory [options] notifications patch -r ... [-p ...] [-o ] - admin1-directory [options] notifications update -r ... [-p ...] [-o ] - admin1-directory [options] orgunits delete ... [-p ...] - admin1-directory [options] orgunits get ... [-p ...] [-o ] - admin1-directory [options] orgunits insert -r ... [-p ...] [-o ] - admin1-directory [options] orgunits list [-p ...] [-o ] - admin1-directory [options] orgunits patch ... -r ... [-p ...] [-o ] - admin1-directory [options] orgunits update ... -r ... [-p ...] [-o ] - admin1-directory [options] schemas delete [-p ...] - admin1-directory [options] schemas get [-p ...] [-o ] - admin1-directory [options] schemas insert -r ... [-p ...] [-o ] - admin1-directory [options] schemas list [-p ...] [-o ] - admin1-directory [options] schemas patch -r ... [-p ...] [-o ] - admin1-directory [options] schemas update -r ... [-p ...] [-o ] - admin1-directory [options] tokens delete [-p ...] - admin1-directory [options] tokens get [-p ...] [-o ] - admin1-directory [options] tokens list [-p ...] [-o ] - admin1-directory [options] users aliases-delete [-p ...] - admin1-directory [options] users aliases-insert -r ... [-p ...] [-o ] - admin1-directory [options] users aliases-list [-p ...] [-o ] - admin1-directory [options] users aliases-watch -r ... [-p ...] [-o ] - admin1-directory [options] users delete [-p ...] - admin1-directory [options] users get [-p ...] [-o ] - admin1-directory [options] users insert -r ... [-p ...] [-o ] - admin1-directory [options] users list [-p ...] [-o ] - admin1-directory [options] users make-admin -r ... [-p ...] - admin1-directory [options] users patch -r ... [-p ...] [-o ] - admin1-directory [options] users photos-delete [-p ...] - admin1-directory [options] users photos-get [-p ...] [-o ] - admin1-directory [options] users photos-patch -r ... [-p ...] [-o ] - admin1-directory [options] users photos-update -r ... [-p ...] [-o ] - admin1-directory [options] users undelete -r ... [-p ...] - admin1-directory [options] users update -r ... [-p ...] [-o ] - admin1-directory [options] users watch -r ... [-p ...] [-o ] - admin1-directory [options] verification-codes generate [-p ...] - admin1-directory [options] verification-codes invalidate [-p ...] - admin1-directory [options] verification-codes list [-p ...] [-o ] +admin1-directory [options] + asps + delete [-p ]... + get [-p ]... [-o ] + list [-p ]... [-o ] + channels + stop (-r )... [-p ]... + chromeosdevices + get [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + groups + aliases-delete [-p ]... + aliases-insert (-r )... [-p ]... [-o ] + aliases-list [-p ]... [-o ] + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + members + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + mobiledevices + action (-r )... [-p ]... + delete [-p ]... + get [-p ]... [-o ] + list [-p ]... [-o ] + notifications + delete [-p ]... + get [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + orgunits + delete ... [-p ]... + get ... [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch ... (-r )... [-p ]... [-o ] + update ... (-r )... [-p ]... [-o ] + schemas + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + tokens + delete [-p ]... + get [-p ]... [-o ] + list [-p ]... [-o ] + users + aliases-delete [-p ]... + aliases-insert (-r )... [-p ]... [-o ] + aliases-list [-p ]... [-o ] + aliases-watch (-r )... [-p ]... [-o ] + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + make-admin (-r )... [-p ]... + patch (-r )... [-p ]... [-o ] + photos-delete [-p ]... + photos-get [-p ]... [-o ] + photos-patch (-r )... [-p ]... [-o ] + photos-update (-r )... [-p ]... [-o ] + undelete (-r )... [-p ]... + update (-r )... [-p ]... [-o ] + watch (-r )... [-p ]... [-o ] + verification-codes + generate [-p ]... + invalidate [-p ]... + list [-p ]... [-o ] admin1-directory --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_admin1_directory_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/admin1_directory-cli/mkdocs.yml b/gen/admin1_directory-cli/mkdocs.yml index 3ec3f9cd3a..50de9949ec 100644 --- a/gen/admin1_directory-cli/mkdocs.yml +++ b/gen/admin1_directory-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: directory v0.1.0+20150314 +site_name: directory v0.2.0+20150314 site_url: http://byron.github.io/google-apis-rs/google-admin1_directory-cli site_description: Write integrating applications with bcore diff --git a/gen/admin1_directory-cli/src/cmn.rs b/gen/admin1_directory-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/admin1_directory-cli/src/cmn.rs +++ b/gen/admin1_directory-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/admin1_directory-cli/src/main.rs b/gen/admin1_directory-cli/src/main.rs index 97cd9500ca..c62b477e4f 100644 --- a/gen/admin1_directory-cli/src/main.rs +++ b/gen/admin1_directory-cli/src/main.rs @@ -2,273 +2,200 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_admin1_directory as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - admin1-directory [options] asps delete [-p ...] - admin1-directory [options] asps get [-p ...] [-o ] - admin1-directory [options] asps list [-p ...] [-o ] - admin1-directory [options] channels stop -r ... [-p ...] - admin1-directory [options] chromeosdevices get [-p ...] [-o ] - admin1-directory [options] chromeosdevices list [-p ...] [-o ] - admin1-directory [options] chromeosdevices patch -r ... [-p ...] [-o ] - admin1-directory [options] chromeosdevices update -r ... [-p ...] [-o ] - admin1-directory [options] groups aliases-delete [-p ...] - admin1-directory [options] groups aliases-insert -r ... [-p ...] [-o ] - admin1-directory [options] groups aliases-list [-p ...] [-o ] - admin1-directory [options] groups delete [-p ...] - admin1-directory [options] groups get [-p ...] [-o ] - admin1-directory [options] groups insert -r ... [-p ...] [-o ] - admin1-directory [options] groups list [-p ...] [-o ] - admin1-directory [options] groups patch -r ... [-p ...] [-o ] - admin1-directory [options] groups update -r ... [-p ...] [-o ] - admin1-directory [options] members delete [-p ...] - admin1-directory [options] members get [-p ...] [-o ] - admin1-directory [options] members insert -r ... [-p ...] [-o ] - admin1-directory [options] members list [-p ...] [-o ] - admin1-directory [options] members patch -r ... [-p ...] [-o ] - admin1-directory [options] members update -r ... [-p ...] [-o ] - admin1-directory [options] mobiledevices action -r ... [-p ...] - admin1-directory [options] mobiledevices delete [-p ...] - admin1-directory [options] mobiledevices get [-p ...] [-o ] - admin1-directory [options] mobiledevices list [-p ...] [-o ] - admin1-directory [options] notifications delete [-p ...] - admin1-directory [options] notifications get [-p ...] [-o ] - admin1-directory [options] notifications list [-p ...] [-o ] - admin1-directory [options] notifications patch -r ... [-p ...] [-o ] - admin1-directory [options] notifications update -r ... [-p ...] [-o ] - admin1-directory [options] orgunits delete ... [-p ...] - admin1-directory [options] orgunits get ... [-p ...] [-o ] - admin1-directory [options] orgunits insert -r ... [-p ...] [-o ] - admin1-directory [options] orgunits list [-p ...] [-o ] - admin1-directory [options] orgunits patch ... -r ... [-p ...] [-o ] - admin1-directory [options] orgunits update ... -r ... [-p ...] [-o ] - admin1-directory [options] schemas delete [-p ...] - admin1-directory [options] schemas get [-p ...] [-o ] - admin1-directory [options] schemas insert -r ... [-p ...] [-o ] - admin1-directory [options] schemas list [-p ...] [-o ] - admin1-directory [options] schemas patch -r ... [-p ...] [-o ] - admin1-directory [options] schemas update -r ... [-p ...] [-o ] - admin1-directory [options] tokens delete [-p ...] - admin1-directory [options] tokens get [-p ...] [-o ] - admin1-directory [options] tokens list [-p ...] [-o ] - admin1-directory [options] users aliases-delete [-p ...] - admin1-directory [options] users aliases-insert -r ... [-p ...] [-o ] - admin1-directory [options] users aliases-list [-p ...] [-o ] - admin1-directory [options] users aliases-watch -r ... [-p ...] [-o ] - admin1-directory [options] users delete [-p ...] - admin1-directory [options] users get [-p ...] [-o ] - admin1-directory [options] users insert -r ... [-p ...] [-o ] - admin1-directory [options] users list [-p ...] [-o ] - admin1-directory [options] users make-admin -r ... [-p ...] - admin1-directory [options] users patch -r ... [-p ...] [-o ] - admin1-directory [options] users photos-delete [-p ...] - admin1-directory [options] users photos-get [-p ...] [-o ] - admin1-directory [options] users photos-patch -r ... [-p ...] [-o ] - admin1-directory [options] users photos-update -r ... [-p ...] [-o ] - admin1-directory [options] users undelete -r ... [-p ...] - admin1-directory [options] users update -r ... [-p ...] [-o ] - admin1-directory [options] users watch -r ... [-p ...] [-o ] - admin1-directory [options] verification-codes generate [-p ...] - admin1-directory [options] verification-codes invalidate [-p ...] - admin1-directory [options] verification-codes list [-p ...] [-o ] - admin1-directory --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_admin1_directory_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Directory>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _asps_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let code_id: i32 = arg_from_str(&self.opt.arg_code_id, err, "", "integer"); - let mut call = self.hub.asps().delete(&self.opt.arg_user_key, code_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _asps_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let code_id: i32 = arg_from_str(&opt.value_of("code-id").unwrap_or(""), err, "", "integer"); + let mut call = self.hub.asps().delete(opt.value_of("user-key").unwrap_or(""), code_id); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _asps_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let code_id: i32 = arg_from_str(&self.opt.arg_code_id, err, "", "integer"); - let mut call = self.hub.asps().get(&self.opt.arg_user_key, code_id); - for parg in self.opt.arg_v.iter() { + fn _asps_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let code_id: i32 = arg_from_str(&opt.value_of("code-id").unwrap_or(""), err, "", "integer"); + let mut call = self.hub.asps().get(opt.value_of("user-key").unwrap_or(""), code_id); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _asps_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.asps().list(&self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + fn _asps_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.asps().list(opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _channels_stop(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _channels_stop(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Channel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -318,105 +245,109 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.channels().stop(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _chromeosdevices_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.chromeosdevices().get(&self.opt.arg_customer_id, &self.opt.arg_device_id); - for parg in self.opt.arg_v.iter() { + fn _chromeosdevices_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.chromeosdevices().get(opt.value_of("customer-id").unwrap_or(""), opt.value_of("device-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { call = call.projection(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["projection"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _chromeosdevices_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.chromeosdevices().list(&self.opt.arg_customer_id); - for parg in self.opt.arg_v.iter() { + fn _chromeosdevices_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.chromeosdevices().list(opt.value_of("customer-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "sort-order" => { @@ -437,52 +368,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["order-by", "projection", "max-results", "page-token", "sort-order", "query"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _chromeosdevices_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _chromeosdevices_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ChromeOsDevice::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -567,63 +502,68 @@ impl Engine { request.model = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["annotated-asset-id", "annotated-location", "annotated-user", "boot-mode", "device-id", "etag", "ethernet-mac-address", "firmware-version", "kind", "last-enrollment-time", "last-sync", "mac-address", "meid", "model", "notes", "order-number", "org-unit-path", "os-version", "platform-version", "serial-number", "status", "support-end-date", "will-auto-renew"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.chromeosdevices().patch(request, &self.opt.arg_customer_id, &self.opt.arg_device_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.chromeosdevices().patch(request, opt.value_of("customer-id").unwrap_or(""), opt.value_of("device-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { call = call.projection(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["projection"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _chromeosdevices_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _chromeosdevices_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ChromeOsDevice::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -708,107 +648,111 @@ impl Engine { request.model = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["annotated-asset-id", "annotated-location", "annotated-user", "boot-mode", "device-id", "etag", "ethernet-mac-address", "firmware-version", "kind", "last-enrollment-time", "last-sync", "mac-address", "meid", "model", "notes", "order-number", "org-unit-path", "os-version", "platform-version", "serial-number", "status", "support-end-date", "will-auto-renew"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.chromeosdevices().update(request, &self.opt.arg_customer_id, &self.opt.arg_device_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.chromeosdevices().update(request, opt.value_of("customer-id").unwrap_or(""), opt.value_of("device-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { call = call.projection(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["projection"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _groups_aliases_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.groups().aliases_delete(&self.opt.arg_group_key, &self.opt.arg_alias); - for parg in self.opt.arg_v.iter() { + fn _groups_aliases_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.groups().aliases_delete(opt.value_of("group-key").unwrap_or(""), opt.value_of("alias").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _groups_aliases_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _groups_aliases_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Alias::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -839,196 +783,208 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["alias", "etag", "id", "kind", "primary-email"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.groups().aliases_insert(request, &self.opt.arg_group_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.groups().aliases_insert(request, opt.value_of("group-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _groups_aliases_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.groups().aliases_list(&self.opt.arg_group_key); - for parg in self.opt.arg_v.iter() { + fn _groups_aliases_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.groups().aliases_list(opt.value_of("group-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _groups_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.groups().delete(&self.opt.arg_group_key); - for parg in self.opt.arg_v.iter() { + fn _groups_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.groups().delete(opt.value_of("group-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _groups_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.groups().get(&self.opt.arg_group_key); - for parg in self.opt.arg_v.iter() { + fn _groups_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.groups().get(opt.value_of("group-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _groups_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _groups_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Group::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1080,58 +1036,63 @@ impl Engine { request.aliases.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["admin-created", "aliases", "description", "direct-members-count", "email", "etag", "id", "kind", "name", "non-editable-aliases"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.groups().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _groups_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _groups_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.groups().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "user-key" => { @@ -1149,52 +1110,56 @@ impl Engine { "customer" => { call = call.customer(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["customer", "user-key", "domain", "max-results", "page-token"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _groups_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _groups_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Group::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1246,60 +1211,65 @@ impl Engine { request.aliases.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["admin-created", "aliases", "description", "direct-members-count", "email", "etag", "id", "kind", "name", "non-editable-aliases"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.groups().patch(request, &self.opt.arg_group_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.groups().patch(request, opt.value_of("group-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _groups_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _groups_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Group::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1351,150 +1321,158 @@ impl Engine { request.aliases.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["admin-created", "aliases", "description", "direct-members-count", "email", "etag", "id", "kind", "name", "non-editable-aliases"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.groups().update(request, &self.opt.arg_group_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.groups().update(request, opt.value_of("group-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _members_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.members().delete(&self.opt.arg_group_key, &self.opt.arg_member_key); - for parg in self.opt.arg_v.iter() { + fn _members_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.members().delete(opt.value_of("group-key").unwrap_or(""), opt.value_of("member-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _members_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.members().get(&self.opt.arg_group_key, &self.opt.arg_member_key); - for parg in self.opt.arg_v.iter() { + fn _members_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.members().get(opt.value_of("group-key").unwrap_or(""), opt.value_of("member-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _members_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _members_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Member::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1528,58 +1506,63 @@ impl Engine { request.email = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["email", "etag", "id", "kind", "role", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.members().insert(request, &self.opt.arg_group_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.members().insert(request, opt.value_of("group-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _members_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.members().list(&self.opt.arg_group_key); - for parg in self.opt.arg_v.iter() { + fn _members_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.members().list(opt.value_of("group-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "roles" => { @@ -1591,52 +1574,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results", "roles"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _members_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _members_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Member::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1670,60 +1657,65 @@ impl Engine { request.email = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["email", "etag", "id", "kind", "role", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.members().patch(request, &self.opt.arg_group_key, &self.opt.arg_member_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.members().patch(request, opt.value_of("group-key").unwrap_or(""), opt.value_of("member-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _members_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _members_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Member::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1757,60 +1749,65 @@ impl Engine { request.email = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["email", "etag", "id", "kind", "role", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.members().update(request, &self.opt.arg_group_key, &self.opt.arg_member_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.members().update(request, opt.value_of("group-key").unwrap_or(""), opt.value_of("member-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _mobiledevices_action(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _mobiledevices_action(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::MobileDeviceAction::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1829,149 +1826,152 @@ impl Engine { request.action = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["action"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.mobiledevices().action(request, &self.opt.arg_customer_id, &self.opt.arg_resource_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.mobiledevices().action(request, opt.value_of("customer-id").unwrap_or(""), opt.value_of("resource-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _mobiledevices_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.mobiledevices().delete(&self.opt.arg_customer_id, &self.opt.arg_resource_id); - for parg in self.opt.arg_v.iter() { + fn _mobiledevices_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.mobiledevices().delete(opt.value_of("customer-id").unwrap_or(""), opt.value_of("resource-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _mobiledevices_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.mobiledevices().get(&self.opt.arg_customer_id, &self.opt.arg_resource_id); - for parg in self.opt.arg_v.iter() { + fn _mobiledevices_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.mobiledevices().get(opt.value_of("customer-id").unwrap_or(""), opt.value_of("resource-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { call = call.projection(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["projection"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _mobiledevices_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.mobiledevices().list(&self.opt.arg_customer_id); - for parg in self.opt.arg_v.iter() { + fn _mobiledevices_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.mobiledevices().list(opt.value_of("customer-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "sort-order" => { @@ -1992,140 +1992,147 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["order-by", "projection", "max-results", "page-token", "sort-order", "query"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _notifications_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.notifications().delete(&self.opt.arg_customer, &self.opt.arg_notification_id); - for parg in self.opt.arg_v.iter() { + fn _notifications_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.notifications().delete(opt.value_of("customer").unwrap_or(""), opt.value_of("notification-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _notifications_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.notifications().get(&self.opt.arg_customer, &self.opt.arg_notification_id); - for parg in self.opt.arg_v.iter() { + fn _notifications_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.notifications().get(opt.value_of("customer").unwrap_or(""), opt.value_of("notification-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _notifications_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.notifications().list(&self.opt.arg_customer); - for parg in self.opt.arg_v.iter() { + fn _notifications_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.notifications().list(opt.value_of("customer").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2137,52 +2144,56 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "language", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _notifications_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _notifications_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Notification::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2222,60 +2233,65 @@ impl Engine { request.subject = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["body", "etag", "from-address", "is-unread", "kind", "notification-id", "send-time", "subject"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.notifications().patch(request, &self.opt.arg_customer, &self.opt.arg_notification_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.notifications().patch(request, opt.value_of("customer").unwrap_or(""), opt.value_of("notification-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _notifications_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _notifications_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Notification::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2315,150 +2331,158 @@ impl Engine { request.subject = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["body", "etag", "from-address", "is-unread", "kind", "notification-id", "send-time", "subject"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.notifications().update(request, &self.opt.arg_customer, &self.opt.arg_notification_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.notifications().update(request, opt.value_of("customer").unwrap_or(""), opt.value_of("notification-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _orgunits_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.orgunits().delete(&self.opt.arg_customer_id, &self.opt.arg_org_unit_path); - for parg in self.opt.arg_v.iter() { + fn _orgunits_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.orgunits().delete(opt.value_of("customer-id").unwrap_or(""), &opt.values_of("org-unit-path").unwrap_or(Vec::new()).iter().map(|&v| v.to_string()).collect::>()); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _orgunits_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.orgunits().get(&self.opt.arg_customer_id, &self.opt.arg_org_unit_path); - for parg in self.opt.arg_v.iter() { + fn _orgunits_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.orgunits().get(opt.value_of("customer-id").unwrap_or(""), &opt.values_of("org-unit-path").unwrap_or(Vec::new()).iter().map(|&v| v.to_string()).collect::>()); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _orgunits_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _orgunits_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::OrgUnit::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2501,58 +2525,63 @@ impl Engine { request.description = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["block-inheritance", "description", "etag", "kind", "name", "org-unit-id", "org-unit-path", "parent-org-unit-id", "parent-org-unit-path"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.orgunits().insert(request, &self.opt.arg_customer_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.orgunits().insert(request, opt.value_of("customer-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _orgunits_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.orgunits().list(&self.opt.arg_customer_id); - for parg in self.opt.arg_v.iter() { + fn _orgunits_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.orgunits().list(opt.value_of("customer-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "type" => { @@ -2561,52 +2590,56 @@ impl Engine { "org-unit-path" => { call = call.org_unit_path(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["type", "org-unit-path"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _orgunits_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _orgunits_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::OrgUnit::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2649,60 +2682,65 @@ impl Engine { request.description = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["block-inheritance", "description", "etag", "kind", "name", "org-unit-id", "org-unit-path", "parent-org-unit-id", "parent-org-unit-path"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.orgunits().patch(request, &self.opt.arg_customer_id, &self.opt.arg_org_unit_path); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.orgunits().patch(request, opt.value_of("customer-id").unwrap_or(""), &opt.values_of("org-unit-path").unwrap_or(Vec::new()).iter().map(|&v| v.to_string()).collect::>()); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _orgunits_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _orgunits_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::OrgUnit::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2745,150 +2783,158 @@ impl Engine { request.description = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["block-inheritance", "description", "etag", "kind", "name", "org-unit-id", "org-unit-path", "parent-org-unit-id", "parent-org-unit-path"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.orgunits().update(request, &self.opt.arg_customer_id, &self.opt.arg_org_unit_path); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.orgunits().update(request, opt.value_of("customer-id").unwrap_or(""), &opt.values_of("org-unit-path").unwrap_or(Vec::new()).iter().map(|&v| v.to_string()).collect::>()); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _schemas_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.schemas().delete(&self.opt.arg_customer_id, &self.opt.arg_schema_key); - for parg in self.opt.arg_v.iter() { + fn _schemas_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.schemas().delete(opt.value_of("customer-id").unwrap_or(""), opt.value_of("schema-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _schemas_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.schemas().get(&self.opt.arg_customer_id, &self.opt.arg_schema_key); - for parg in self.opt.arg_v.iter() { + fn _schemas_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.schemas().get(opt.value_of("customer-id").unwrap_or(""), opt.value_of("schema-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _schemas_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _schemas_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Schema::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2916,106 +2962,115 @@ impl Engine { request.schema_name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "kind", "schema-id", "schema-name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.schemas().insert(request, &self.opt.arg_customer_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.schemas().insert(request, opt.value_of("customer-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _schemas_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.schemas().list(&self.opt.arg_customer_id); - for parg in self.opt.arg_v.iter() { + fn _schemas_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.schemas().list(opt.value_of("customer-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _schemas_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _schemas_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Schema::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3043,60 +3098,65 @@ impl Engine { request.schema_name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "kind", "schema-id", "schema-name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.schemas().patch(request, &self.opt.arg_customer_id, &self.opt.arg_schema_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.schemas().patch(request, opt.value_of("customer-id").unwrap_or(""), opt.value_of("schema-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _schemas_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _schemas_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Schema::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3124,240 +3184,251 @@ impl Engine { request.schema_name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "kind", "schema-id", "schema-name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.schemas().update(request, &self.opt.arg_customer_id, &self.opt.arg_schema_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.schemas().update(request, opt.value_of("customer-id").unwrap_or(""), opt.value_of("schema-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tokens_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.tokens().delete(&self.opt.arg_user_key, &self.opt.arg_client_id); - for parg in self.opt.arg_v.iter() { + fn _tokens_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tokens().delete(opt.value_of("user-key").unwrap_or(""), opt.value_of("client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _tokens_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.tokens().get(&self.opt.arg_user_key, &self.opt.arg_client_id); - for parg in self.opt.arg_v.iter() { + fn _tokens_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tokens().get(opt.value_of("user-key").unwrap_or(""), opt.value_of("client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tokens_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.tokens().list(&self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + fn _tokens_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tokens().list(opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_aliases_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.users().aliases_delete(&self.opt.arg_user_key, &self.opt.arg_alias); - for parg in self.opt.arg_v.iter() { + fn _users_aliases_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().aliases_delete(opt.value_of("user-key").unwrap_or(""), opt.value_of("alias").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _users_aliases_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _users_aliases_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Alias::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3388,109 +3459,118 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["alias", "etag", "id", "kind", "primary-email"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().aliases_insert(request, &self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().aliases_insert(request, opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_aliases_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.users().aliases_list(&self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + fn _users_aliases_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().aliases_list(opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "event" => { call = call.event(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["event"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_aliases_watch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _users_aliases_watch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Channel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3540,105 +3620,109 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().aliases_watch(request, &self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().aliases_watch(request, opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "event" => { call = call.event(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["event"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.users().delete(&self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + fn _users_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().delete(opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _users_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.users().get(&self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + fn _users_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().get(opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "view-type" => { @@ -3650,52 +3734,56 @@ impl Engine { "custom-field-mask" => { call = call.custom_field_mask(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["view-type", "custom-field-mask", "projection"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _users_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::User::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3807,58 +3895,63 @@ impl Engine { request.customer_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["agreed-to-terms", "aliases", "change-password-at-next-login", "creation-time", "customer-id", "deletion-time", "etag", "family-name", "full-name", "given-name", "hash-function", "id", "include-in-global-address-list", "ip-whitelisted", "is-admin", "is-delegated-admin", "is-mailbox-setup", "kind", "last-login-time", "name", "non-editable-aliases", "org-unit-path", "password", "primary-email", "suspended", "suspension-reason", "thumbnail-photo-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.users().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _users_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.users().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "view-type" => { @@ -3897,52 +3990,56 @@ impl Engine { "custom-field-mask" => { call = call.custom_field_mask(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["order-by", "customer", "domain", "projection", "page-token", "custom-field-mask", "max-results", "show-deleted", "sort-order", "query", "view-type", "event"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_make_admin(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _users_make_admin(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UserMakeAdmin::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3961,58 +4058,58 @@ impl Engine { request.status = Some(arg_from_str(value.unwrap_or("false"), err, "status", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["status"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().make_admin(request, &self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().make_admin(request, opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _users_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _users_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::User::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4124,150 +4221,158 @@ impl Engine { request.customer_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["agreed-to-terms", "aliases", "change-password-at-next-login", "creation-time", "customer-id", "deletion-time", "etag", "family-name", "full-name", "given-name", "hash-function", "id", "include-in-global-address-list", "ip-whitelisted", "is-admin", "is-delegated-admin", "is-mailbox-setup", "kind", "last-login-time", "name", "non-editable-aliases", "org-unit-path", "password", "primary-email", "suspended", "suspension-reason", "thumbnail-photo-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().patch(request, &self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().patch(request, opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_photos_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.users().photos_delete(&self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + fn _users_photos_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().photos_delete(opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _users_photos_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.users().photos_get(&self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + fn _users_photos_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().photos_get(opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_photos_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _users_photos_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UserPhoto::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4307,60 +4412,65 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "height", "id", "kind", "mime-type", "photo-data", "primary-email", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().photos_patch(request, &self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().photos_patch(request, opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_photos_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _users_photos_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UserPhoto::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4400,60 +4510,65 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "height", "id", "kind", "mime-type", "photo-data", "primary-email", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().photos_update(request, &self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().photos_update(request, opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_undelete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _users_undelete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UserUndelete::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4472,58 +4587,58 @@ impl Engine { request.org_unit_path = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["org-unit-path"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().undelete(request, &self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().undelete(request, opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _users_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _users_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::User::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4635,60 +4750,65 @@ impl Engine { request.customer_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["agreed-to-terms", "aliases", "change-password-at-next-login", "creation-time", "customer-id", "deletion-time", "etag", "family-name", "full-name", "given-name", "hash-function", "id", "include-in-global-address-list", "ip-whitelisted", "is-admin", "is-delegated-admin", "is-mailbox-setup", "kind", "last-login-time", "name", "non-editable-aliases", "org-unit-path", "password", "primary-email", "suspended", "suspension-reason", "thumbnail-photo-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().update(request, &self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().update(request, opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_watch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _users_watch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Channel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4738,12 +4858,13 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.users().watch(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "view-type" => { @@ -4782,394 +4903,508 @@ impl Engine { "custom-field-mask" => { call = call.custom_field_mask(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["order-by", "customer", "domain", "projection", "page-token", "custom-field-mask", "max-results", "show-deleted", "sort-order", "query", "view-type", "event"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _verification_codes_generate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.verification_codes().generate(&self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + fn _verification_codes_generate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.verification_codes().generate(opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _verification_codes_invalidate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.verification_codes().invalidate(&self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + fn _verification_codes_invalidate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.verification_codes().invalidate(opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _verification_codes_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.verification_codes().list(&self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + fn _verification_codes_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.verification_codes().list(opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_asps { - if self.opt.cmd_delete { - call_result = self._asps_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._asps_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._asps_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("asps", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._asps_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._asps_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._asps_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("asps".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("channels", Some(opt)) => { + match opt.subcommand() { + ("stop", Some(opt)) => { + call_result = self._channels_stop(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("channels".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("chromeosdevices", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._chromeosdevices_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._chromeosdevices_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._chromeosdevices_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._chromeosdevices_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("chromeosdevices".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("groups", Some(opt)) => { + match opt.subcommand() { + ("aliases-delete", Some(opt)) => { + call_result = self._groups_aliases_delete(opt, dry_run, &mut err); + }, + ("aliases-insert", Some(opt)) => { + call_result = self._groups_aliases_insert(opt, dry_run, &mut err); + }, + ("aliases-list", Some(opt)) => { + call_result = self._groups_aliases_list(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._groups_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._groups_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._groups_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._groups_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._groups_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._groups_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("groups".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("members", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._members_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._members_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._members_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._members_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._members_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._members_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("members".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("mobiledevices", Some(opt)) => { + match opt.subcommand() { + ("action", Some(opt)) => { + call_result = self._mobiledevices_action(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._mobiledevices_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._mobiledevices_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._mobiledevices_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("mobiledevices".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("notifications", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._notifications_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._notifications_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._notifications_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._notifications_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._notifications_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("notifications".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("orgunits", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._orgunits_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._orgunits_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._orgunits_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._orgunits_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._orgunits_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._orgunits_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("orgunits".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("schemas", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._schemas_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._schemas_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._schemas_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._schemas_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._schemas_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._schemas_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("schemas".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("tokens", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._tokens_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._tokens_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._tokens_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("tokens".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("users", Some(opt)) => { + match opt.subcommand() { + ("aliases-delete", Some(opt)) => { + call_result = self._users_aliases_delete(opt, dry_run, &mut err); + }, + ("aliases-insert", Some(opt)) => { + call_result = self._users_aliases_insert(opt, dry_run, &mut err); + }, + ("aliases-list", Some(opt)) => { + call_result = self._users_aliases_list(opt, dry_run, &mut err); + }, + ("aliases-watch", Some(opt)) => { + call_result = self._users_aliases_watch(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._users_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._users_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._users_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._users_list(opt, dry_run, &mut err); + }, + ("make-admin", Some(opt)) => { + call_result = self._users_make_admin(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._users_patch(opt, dry_run, &mut err); + }, + ("photos-delete", Some(opt)) => { + call_result = self._users_photos_delete(opt, dry_run, &mut err); + }, + ("photos-get", Some(opt)) => { + call_result = self._users_photos_get(opt, dry_run, &mut err); + }, + ("photos-patch", Some(opt)) => { + call_result = self._users_photos_patch(opt, dry_run, &mut err); + }, + ("photos-update", Some(opt)) => { + call_result = self._users_photos_update(opt, dry_run, &mut err); + }, + ("undelete", Some(opt)) => { + call_result = self._users_undelete(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._users_update(opt, dry_run, &mut err); + }, + ("watch", Some(opt)) => { + call_result = self._users_watch(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("users".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("verification-codes", Some(opt)) => { + match opt.subcommand() { + ("generate", Some(opt)) => { + call_result = self._verification_codes_generate(opt, dry_run, &mut err); + }, + ("invalidate", Some(opt)) => { + call_result = self._verification_codes_invalidate(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._verification_codes_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("verification-codes".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_channels { - if self.opt.cmd_stop { - call_result = self._channels_stop(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_chromeosdevices { - if self.opt.cmd_get { - call_result = self._chromeosdevices_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._chromeosdevices_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._chromeosdevices_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._chromeosdevices_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_groups { - if self.opt.cmd_aliases_delete { - call_result = self._groups_aliases_delete(dry_run, &mut err); - } else if self.opt.cmd_aliases_insert { - call_result = self._groups_aliases_insert(dry_run, &mut err); - } else if self.opt.cmd_aliases_list { - call_result = self._groups_aliases_list(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._groups_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._groups_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._groups_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._groups_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._groups_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._groups_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_members { - if self.opt.cmd_delete { - call_result = self._members_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._members_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._members_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._members_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._members_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._members_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_mobiledevices { - if self.opt.cmd_action { - call_result = self._mobiledevices_action(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._mobiledevices_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._mobiledevices_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._mobiledevices_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_notifications { - if self.opt.cmd_delete { - call_result = self._notifications_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._notifications_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._notifications_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._notifications_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._notifications_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_orgunits { - if self.opt.cmd_delete { - call_result = self._orgunits_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._orgunits_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._orgunits_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._orgunits_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._orgunits_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._orgunits_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_schemas { - if self.opt.cmd_delete { - call_result = self._schemas_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._schemas_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._schemas_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._schemas_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._schemas_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._schemas_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_tokens { - if self.opt.cmd_delete { - call_result = self._tokens_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._tokens_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._tokens_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_users { - if self.opt.cmd_aliases_delete { - call_result = self._users_aliases_delete(dry_run, &mut err); - } else if self.opt.cmd_aliases_insert { - call_result = self._users_aliases_insert(dry_run, &mut err); - } else if self.opt.cmd_aliases_list { - call_result = self._users_aliases_list(dry_run, &mut err); - } else if self.opt.cmd_aliases_watch { - call_result = self._users_aliases_watch(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._users_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._users_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._users_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._users_list(dry_run, &mut err); - } else if self.opt.cmd_make_admin { - call_result = self._users_make_admin(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._users_patch(dry_run, &mut err); - } else if self.opt.cmd_photos_delete { - call_result = self._users_photos_delete(dry_run, &mut err); - } else if self.opt.cmd_photos_get { - call_result = self._users_photos_get(dry_run, &mut err); - } else if self.opt.cmd_photos_patch { - call_result = self._users_photos_patch(dry_run, &mut err); - } else if self.opt.cmd_photos_update { - call_result = self._users_photos_update(dry_run, &mut err); - } else if self.opt.cmd_undelete { - call_result = self._users_undelete(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._users_update(dry_run, &mut err); - } else if self.opt.cmd_watch { - call_result = self._users_watch(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_verification_codes { - if self.opt.cmd_generate { - call_result = self._verification_codes_generate(dry_run, &mut err); - } else if self.opt.cmd_invalidate { - call_result = self._verification_codes_invalidate(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._verification_codes_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -5182,7 +5417,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -5195,7 +5430,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -5205,37 +5440,1831 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Directory::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("asps", "methods: 'delete', 'get' and 'list'", vec![ + ("delete", + Some(r##"Delete an ASP issued by a user."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/asps_delete", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID."##), + Some(true), + Some(false)), + + (Some(r##"code-id"##), + None, + Some(r##"The unique ID of the ASP to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Get information about an ASP issued by a user."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/asps_get", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID."##), + Some(true), + Some(false)), + + (Some(r##"code-id"##), + None, + Some(r##"The unique ID of the ASP."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List the ASPs issued by a user."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/asps_list", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("channels", "methods: 'stop'", vec![ + ("stop", + Some(r##"Stop watching resources through this channel"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/channels_stop", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("chromeosdevices", "methods: 'get', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Retrieve Chrome OS Device"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/chromeosdevices_get", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"device-id"##), + None, + Some(r##"Immutable id of Chrome OS Device"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieve all Chrome OS Devices of a customer (paginated)"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/chromeosdevices_list", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update Chrome OS Device. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/chromeosdevices_patch", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"device-id"##), + None, + Some(r##"Immutable id of Chrome OS Device"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update Chrome OS Device"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/chromeosdevices_update", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"device-id"##), + None, + Some(r##"Immutable id of Chrome OS Device"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("groups", "methods: 'aliases-delete', 'aliases-insert', 'aliases-list', 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("aliases-delete", + Some(r##"Remove a alias for the group"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/groups_aliases-delete", + vec![ + (Some(r##"group-key"##), + None, + Some(r##"Email or immutable Id of the group"##), + Some(true), + Some(false)), + + (Some(r##"alias"##), + None, + Some(r##"The alias to be removed"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("aliases-insert", + Some(r##"Add a alias for the group"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/groups_aliases-insert", + vec![ + (Some(r##"group-key"##), + None, + Some(r##"Email or immutable Id of the group"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("aliases-list", + Some(r##"List all aliases for a group"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/groups_aliases-list", + vec![ + (Some(r##"group-key"##), + None, + Some(r##"Email or immutable Id of the group"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Delete Group"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/groups_delete", + vec![ + (Some(r##"group-key"##), + None, + Some(r##"Email or immutable Id of the group"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieve Group"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/groups_get", + vec![ + (Some(r##"group-key"##), + None, + Some(r##"Email or immutable Id of the group"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Create Group"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/groups_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieve all groups in a domain (paginated)"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/groups_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update Group. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/groups_patch", + vec![ + (Some(r##"group-key"##), + None, + Some(r##"Email or immutable Id of the group. If Id, it should match with id of group object"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update Group"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/groups_update", + vec![ + (Some(r##"group-key"##), + None, + Some(r##"Email or immutable Id of the group. If Id, it should match with id of group object"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("members", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Remove membership."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/members_delete", + vec![ + (Some(r##"group-key"##), + None, + Some(r##"Email or immutable Id of the group"##), + Some(true), + Some(false)), + + (Some(r##"member-key"##), + None, + Some(r##"Email or immutable Id of the member"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieve Group Member"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/members_get", + vec![ + (Some(r##"group-key"##), + None, + Some(r##"Email or immutable Id of the group"##), + Some(true), + Some(false)), + + (Some(r##"member-key"##), + None, + Some(r##"Email or immutable Id of the member"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Add user to the specified group."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/members_insert", + vec![ + (Some(r##"group-key"##), + None, + Some(r##"Email or immutable Id of the group"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieve all members in a group (paginated)"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/members_list", + vec![ + (Some(r##"group-key"##), + None, + Some(r##"Email or immutable Id of the group"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update membership of a user in the specified group. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/members_patch", + vec![ + (Some(r##"group-key"##), + None, + Some(r##"Email or immutable Id of the group. If Id, it should match with id of group object"##), + Some(true), + Some(false)), + + (Some(r##"member-key"##), + None, + Some(r##"Email or immutable Id of the user. If Id, it should match with id of member object"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update membership of a user in the specified group."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/members_update", + vec![ + (Some(r##"group-key"##), + None, + Some(r##"Email or immutable Id of the group. If Id, it should match with id of group object"##), + Some(true), + Some(false)), + + (Some(r##"member-key"##), + None, + Some(r##"Email or immutable Id of the user. If Id, it should match with id of member object"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("mobiledevices", "methods: 'action', 'delete', 'get' and 'list'", vec![ + ("action", + Some(r##"Take action on Mobile Device"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/mobiledevices_action", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"resource-id"##), + None, + Some(r##"Immutable id of Mobile Device"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("delete", + Some(r##"Delete Mobile Device"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/mobiledevices_delete", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"resource-id"##), + None, + Some(r##"Immutable id of Mobile Device"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieve Mobile Device"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/mobiledevices_get", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"resource-id"##), + None, + Some(r##"Immutable id of Mobile Device"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieve all Mobile Devices of a customer (paginated)"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/mobiledevices_list", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("notifications", "methods: 'delete', 'get', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes a notification"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/notifications_delete", + vec![ + (Some(r##"customer"##), + None, + Some(r##"The unique ID for the customer's Google account. The customerId is also returned as part of the Users resource."##), + Some(true), + Some(false)), + + (Some(r##"notification-id"##), + None, + Some(r##"The unique ID of the notification."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves a notification."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/notifications_get", + vec![ + (Some(r##"customer"##), + None, + Some(r##"The unique ID for the customer's Google account. The customerId is also returned as part of the Users resource."##), + Some(true), + Some(false)), + + (Some(r##"notification-id"##), + None, + Some(r##"The unique ID of the notification."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of notifications."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/notifications_list", + vec![ + (Some(r##"customer"##), + None, + Some(r##"The unique ID for the customer's Google account."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a notification. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/notifications_patch", + vec![ + (Some(r##"customer"##), + None, + Some(r##"The unique ID for the customer's Google account."##), + Some(true), + Some(false)), + + (Some(r##"notification-id"##), + None, + Some(r##"The unique ID of the notification."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a notification."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/notifications_update", + vec![ + (Some(r##"customer"##), + None, + Some(r##"The unique ID for the customer's Google account."##), + Some(true), + Some(false)), + + (Some(r##"notification-id"##), + None, + Some(r##"The unique ID of the notification."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("orgunits", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Remove Organization Unit"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/orgunits_delete", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"org-unit-path"##), + None, + Some(r##"Full path of the organization unit or its Id"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieve Organization Unit"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/orgunits_get", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"org-unit-path"##), + None, + Some(r##"Full path of the organization unit or its Id"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Add Organization Unit"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/orgunits_insert", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieve all Organization Units"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/orgunits_list", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update Organization Unit. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/orgunits_patch", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"org-unit-path"##), + None, + Some(r##"Full path of the organization unit or its Id"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update Organization Unit"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/orgunits_update", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"org-unit-path"##), + None, + Some(r##"Full path of the organization unit or its Id"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("schemas", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Delete schema"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/schemas_delete", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"schema-key"##), + None, + Some(r##"Name or immutable Id of the schema"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieve schema"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/schemas_get", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"schema-key"##), + None, + Some(r##"Name or immutable Id of the schema"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Create schema."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/schemas_insert", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieve all schemas for a customer"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/schemas_list", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update schema. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/schemas_patch", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"schema-key"##), + None, + Some(r##"Name or immutable Id of the schema."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update schema"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/schemas_update", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Immutable id of the Google Apps account"##), + Some(true), + Some(false)), + + (Some(r##"schema-key"##), + None, + Some(r##"Name or immutable Id of the schema."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("tokens", "methods: 'delete', 'get' and 'list'", vec![ + ("delete", + Some(r##"Delete all access tokens issued by a user for an application."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/tokens_delete", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID."##), + Some(true), + Some(false)), + + (Some(r##"client-id"##), + None, + Some(r##"The Client ID of the application the token is issued to."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Get information about an access token issued by a user."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/tokens_get", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID."##), + Some(true), + Some(false)), + + (Some(r##"client-id"##), + None, + Some(r##"The Client ID of the application the token is issued to."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Returns the set of tokens specified user has issued to 3rd party applications."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/tokens_list", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("users", "methods: 'aliases-delete', 'aliases-insert', 'aliases-list', 'aliases-watch', 'delete', 'get', 'insert', 'list', 'make-admin', 'patch', 'photos-delete', 'photos-get', 'photos-patch', 'photos-update', 'undelete', 'update' and 'watch'", vec![ + ("aliases-delete", + Some(r##"Remove a alias for the user"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_aliases-delete", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"alias"##), + None, + Some(r##"The alias to be removed"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("aliases-insert", + Some(r##"Add a alias for the user"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_aliases-insert", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("aliases-list", + Some(r##"List all aliases for a user"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_aliases-list", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("aliases-watch", + Some(r##"Watch for changes in user aliases list"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_aliases-watch", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Delete user"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_delete", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"retrieve user"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_get", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"create user."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieve either deleted users or all users in a domain (paginated)"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("make-admin", + Some(r##"change admin status of a user"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_make-admin", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user as admin"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("patch", + Some(r##"update user. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_patch", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user. If Id, it should match with id of user object"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("photos-delete", + Some(r##"Remove photos for the user"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_photos-delete", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("photos-get", + Some(r##"Retrieve photo of a user"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_photos-get", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("photos-patch", + Some(r##"Add a photo for the user. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_photos-patch", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("photos-update", + Some(r##"Add a photo for the user"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_photos-update", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("undelete", + Some(r##"Undelete a deleted user"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_undelete", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"The immutable id of the user"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("update", + Some(r##"update user"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_update", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user. If Id, it should match with id of user object"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("watch", + Some(r##"Watch for changes in users list"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/users_watch", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("verification-codes", "methods: 'generate', 'invalidate' and 'list'", vec![ + ("generate", + Some(r##"Generate new backup verification codes for the user."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/verification-codes_generate", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("invalidate", + Some(r##"Invalidate the current backup verification codes for the user."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/verification-codes_invalidate", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Email or immutable Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("list", + Some(r##"Returns the current set of valid backup verification codes for the specified user."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_directory_cli/verification-codes_list", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Identifies the user in the API request. The value can be the user's primary email address, alias email address, or unique user ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("admin1-directory") + .author("Sebastian Thiel ") + .version("0.2.0+20150314") + .about("The Admin SDK Directory API lets you view and manage enterprise resources such as users and groups, administrative notifications, security features, and more.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_admin1_directory_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/admin1_directory/Cargo.toml b/gen/admin1_directory/Cargo.toml index 4e99cbecf1..b66e5a1f20 100644 --- a/gen/admin1_directory/Cargo.toml +++ b/gen/admin1_directory/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-admin1_directory" -version = "0.1.6+20150314" +version = "0.1.7+20150314" authors = ["Sebastian Thiel "] description = "A complete library to interact with directory (protocol directory_v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/admin1_directory" @@ -15,9 +15,10 @@ keywords = ["admin", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/admin1_directory/README.md b/gen/admin1_directory/README.md index 9924afc27b..8f8924db00 100644 --- a/gen/admin1_directory/README.md +++ b/gen/admin1_directory/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-admin1_directory` library allows access to all features of the *Google directory* service. -This documentation was generated from *directory* crate version *0.1.6+20150314*, where *20150314* is the exact revision of the *admin:directory_v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *directory* crate version *0.1.7+20150314*, where *20150314* is the exact revision of the *admin:directory_v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *directory* *v1_directory* API can be found at the [official documentation site](https://developers.google.com/admin-sdk/directory/). @@ -221,7 +221,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_admin1_directory/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_admin1_directory/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/admin1_directory/src/cmn.rs b/gen/admin1_directory/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/admin1_directory/src/cmn.rs +++ b/gen/admin1_directory/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/admin1_directory/src/lib.rs b/gen/admin1_directory/src/lib.rs index 3d6b0d0b6e..04f2fb314b 100644 --- a/gen/admin1_directory/src/lib.rs +++ b/gen/admin1_directory/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *directory* crate version *0.1.6+20150314*, where *20150314* is the exact revision of the *admin:directory_v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *directory* crate version *0.1.7+20150314*, where *20150314* is the exact revision of the *admin:directory_v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *directory* *v1_directory* API can be found at the //! [official documentation site](https://developers.google.com/admin-sdk/directory/). @@ -222,7 +222,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -231,7 +231,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -247,6 +246,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -453,7 +453,7 @@ impl<'a, C, A> Directory Directory { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -495,7 +495,7 @@ impl<'a, C, A> Directory } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -3611,7 +3611,7 @@ impl<'a, C, A> TokenGetCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3633,7 +3633,7 @@ impl<'a, C, A> TokenGetCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3860,7 +3860,7 @@ impl<'a, C, A> TokenListCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3882,7 +3882,7 @@ impl<'a, C, A> TokenListCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4100,7 +4100,7 @@ impl<'a, C, A> TokenDeleteCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4122,7 +4122,7 @@ impl<'a, C, A> TokenDeleteCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4290,6 +4290,7 @@ impl<'a, C, A> ChannelStopCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4319,11 +4320,20 @@ impl<'a, C, A> ChannelStopCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4346,7 +4356,7 @@ impl<'a, C, A> ChannelStopCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4507,6 +4517,7 @@ impl<'a, C, A> OrgunitInsertCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, OrgUnit)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4562,11 +4573,20 @@ impl<'a, C, A> OrgunitInsertCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4589,7 +4609,7 @@ impl<'a, C, A> OrgunitInsertCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4828,7 +4848,7 @@ impl<'a, C, A> OrgunitListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4850,7 +4870,7 @@ impl<'a, C, A> OrgunitListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5089,7 +5109,7 @@ impl<'a, C, A> OrgunitGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5111,7 +5131,7 @@ impl<'a, C, A> OrgunitGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5292,6 +5312,7 @@ impl<'a, C, A> OrgunitUpdateCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, OrgUnit)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5354,11 +5375,20 @@ impl<'a, C, A> OrgunitUpdateCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5381,7 +5411,7 @@ impl<'a, C, A> OrgunitUpdateCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5628,7 +5658,7 @@ impl<'a, C, A> OrgunitDeleteCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5650,7 +5680,7 @@ impl<'a, C, A> OrgunitDeleteCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5821,6 +5851,7 @@ impl<'a, C, A> OrgunitPatchCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, OrgUnit)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5883,11 +5914,20 @@ impl<'a, C, A> OrgunitPatchCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5910,7 +5950,7 @@ impl<'a, C, A> OrgunitPatchCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6101,6 +6141,7 @@ impl<'a, C, A> UserInsertCall<'a, C, A> where C: BorrowMut, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, User)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6131,11 +6172,20 @@ impl<'a, C, A> UserInsertCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6158,7 +6208,7 @@ impl<'a, C, A> UserInsertCall<'a, C, A> where C: BorrowMut, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6376,7 +6426,7 @@ impl<'a, C, A> UserPhotoDeleteCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6398,7 +6448,7 @@ impl<'a, C, A> UserPhotoDeleteCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6557,6 +6607,7 @@ impl<'a, C, A> UserUndeleteCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6611,11 +6662,20 @@ impl<'a, C, A> UserUndeleteCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6638,7 +6698,7 @@ impl<'a, C, A> UserUndeleteCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6809,6 +6869,7 @@ impl<'a, C, A> UserMakeAdminCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6863,11 +6924,20 @@ impl<'a, C, A> UserMakeAdminCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6890,7 +6960,7 @@ impl<'a, C, A> UserMakeAdminCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7061,6 +7131,7 @@ impl<'a, C, A> UserPatchCall<'a, C, A> where C: BorrowMut, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, User)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7116,11 +7187,20 @@ impl<'a, C, A> UserPatchCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7143,7 +7223,7 @@ impl<'a, C, A> UserPatchCall<'a, C, A> where C: BorrowMut, A: oau request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7347,6 +7427,7 @@ impl<'a, C, A> UserWatchCall<'a, C, A> where C: BorrowMut, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Channel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7413,11 +7494,20 @@ impl<'a, C, A> UserWatchCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7440,7 +7530,7 @@ impl<'a, C, A> UserWatchCall<'a, C, A> where C: BorrowMut, A: oau request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7742,7 +7832,7 @@ impl<'a, C, A> UserDeleteCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7764,7 +7854,7 @@ impl<'a, C, A> UserDeleteCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7923,6 +8013,7 @@ impl<'a, C, A> UserPhotoUpdateCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, UserPhoto)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7978,11 +8069,20 @@ impl<'a, C, A> UserPhotoUpdateCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8005,7 +8105,7 @@ impl<'a, C, A> UserPhotoUpdateCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8249,7 +8349,7 @@ impl<'a, C, A> UserGetCall<'a, C, A> where C: BorrowMut, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8271,7 +8371,7 @@ impl<'a, C, A> UserGetCall<'a, C, A> where C: BorrowMut, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8461,6 +8561,7 @@ impl<'a, C, A> UserAliaseInsertCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Alias)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8516,11 +8617,20 @@ impl<'a, C, A> UserAliaseInsertCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8543,7 +8653,7 @@ impl<'a, C, A> UserAliaseInsertCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8806,7 +8916,7 @@ impl<'a, C, A> UserListCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8828,7 +8938,7 @@ impl<'a, C, A> UserListCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9120,7 +9230,7 @@ impl<'a, C, A> UserAliaseDeleteCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9142,7 +9252,7 @@ impl<'a, C, A> UserAliaseDeleteCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9311,6 +9421,7 @@ impl<'a, C, A> UserUpdateCall<'a, C, A> where C: BorrowMut, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, User)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9366,11 +9477,20 @@ impl<'a, C, A> UserUpdateCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9393,7 +9513,7 @@ impl<'a, C, A> UserUpdateCall<'a, C, A> where C: BorrowMut, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9576,6 +9696,7 @@ impl<'a, C, A> UserAliaseWatchCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Channel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9634,11 +9755,20 @@ impl<'a, C, A> UserAliaseWatchCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9661,7 +9791,7 @@ impl<'a, C, A> UserAliaseWatchCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9902,7 +10032,7 @@ impl<'a, C, A> UserAliaseListCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9924,7 +10054,7 @@ impl<'a, C, A> UserAliaseListCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10148,7 +10278,7 @@ impl<'a, C, A> UserPhotoGetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10170,7 +10300,7 @@ impl<'a, C, A> UserPhotoGetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10339,6 +10469,7 @@ impl<'a, C, A> UserPhotoPatchCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, UserPhoto)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10394,11 +10525,20 @@ impl<'a, C, A> UserPhotoPatchCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10421,7 +10561,7 @@ impl<'a, C, A> UserPhotoPatchCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -10651,7 +10791,7 @@ impl<'a, C, A> MobiledeviceDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10673,7 +10813,7 @@ impl<'a, C, A> MobiledeviceDeleteCall<'a, C, A> where C: BorrowMut MobiledeviceGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10919,7 +11059,7 @@ impl<'a, C, A> MobiledeviceGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11183,7 +11323,7 @@ impl<'a, C, A> MobiledeviceListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11205,7 +11345,7 @@ impl<'a, C, A> MobiledeviceListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11417,6 +11557,7 @@ impl<'a, C, A> MobiledeviceActionCall<'a, C, A> where C: BorrowMut Result { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11472,11 +11613,20 @@ impl<'a, C, A> MobiledeviceActionCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11499,7 +11649,7 @@ impl<'a, C, A> MobiledeviceActionCall<'a, C, A> where C: BorrowMut MemberUpdateCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Member)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11737,11 +11888,20 @@ impl<'a, C, A> MemberUpdateCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11764,7 +11924,7 @@ impl<'a, C, A> MemberUpdateCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -12005,7 +12165,7 @@ impl<'a, C, A> MemberGetCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12027,7 +12187,7 @@ impl<'a, C, A> MemberGetCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12206,6 +12366,7 @@ impl<'a, C, A> MemberInsertCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Member)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12261,11 +12422,20 @@ impl<'a, C, A> MemberInsertCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12288,7 +12458,7 @@ impl<'a, C, A> MemberInsertCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -12470,6 +12640,7 @@ impl<'a, C, A> MemberPatchCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Member)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12526,11 +12697,20 @@ impl<'a, C, A> MemberPatchCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12553,7 +12733,7 @@ impl<'a, C, A> MemberPatchCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -12793,7 +12973,7 @@ impl<'a, C, A> MemberDeleteCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12815,7 +12995,7 @@ impl<'a, C, A> MemberDeleteCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -13047,7 +13227,7 @@ impl<'a, C, A> MemberListCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13069,7 +13249,7 @@ impl<'a, C, A> MemberListCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -13322,7 +13502,7 @@ impl<'a, C, A> NotificationListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13344,7 +13524,7 @@ impl<'a, C, A> NotificationListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -13583,7 +13763,7 @@ impl<'a, C, A> NotificationDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13605,7 +13785,7 @@ impl<'a, C, A> NotificationDeleteCall<'a, C, A> where C: BorrowMut NotificationPatchCall<'a, C, A> where C: BorrowMut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Notification)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13831,11 +14012,20 @@ impl<'a, C, A> NotificationPatchCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13858,7 +14048,7 @@ impl<'a, C, A> NotificationPatchCall<'a, C, A> where C: BorrowMut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -14050,6 +14240,7 @@ impl<'a, C, A> NotificationUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Notification)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14106,11 +14297,20 @@ impl<'a, C, A> NotificationUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14133,7 +14333,7 @@ impl<'a, C, A> NotificationUpdateCall<'a, C, A> where C: BorrowMut NotificationGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14396,7 +14596,7 @@ impl<'a, C, A> NotificationGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -14653,7 +14853,7 @@ impl<'a, C, A> ChromeosdeviceListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14675,7 +14875,7 @@ impl<'a, C, A> ChromeosdeviceListCall<'a, C, A> where C: BorrowMut ChromeosdevicePatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, ChromeOsDevice)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14948,11 +15149,20 @@ impl<'a, C, A> ChromeosdevicePatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14975,7 +15185,7 @@ impl<'a, C, A> ChromeosdevicePatchCall<'a, C, A> where C: BorrowMut ChromeosdeviceGetCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15250,7 +15460,7 @@ impl<'a, C, A> ChromeosdeviceGetCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -15439,6 +15649,7 @@ impl<'a, C, A> ChromeosdeviceUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, ChromeOsDevice)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15498,11 +15709,20 @@ impl<'a, C, A> ChromeosdeviceUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15525,7 +15745,7 @@ impl<'a, C, A> ChromeosdeviceUpdateCall<'a, C, A> where C: BorrowMut VerificationCodeGenerateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15792,7 +16012,7 @@ impl<'a, C, A> VerificationCodeGenerateCall<'a, C, A> where C: BorrowMut VerificationCodeInvalidateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16020,7 +16240,7 @@ impl<'a, C, A> VerificationCodeInvalidateCall<'a, C, A> where C: BorrowMut VerificationCodeListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16249,7 +16469,7 @@ impl<'a, C, A> VerificationCodeListCall<'a, C, A> where C: BorrowMut GroupGetCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16488,7 +16708,7 @@ impl<'a, C, A> GroupGetCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -16704,7 +16924,7 @@ impl<'a, C, A> GroupListCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16726,7 +16946,7 @@ impl<'a, C, A> GroupListCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -16968,7 +17188,7 @@ impl<'a, C, A> GroupAliaseListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16990,7 +17210,7 @@ impl<'a, C, A> GroupAliaseListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -17159,6 +17379,7 @@ impl<'a, C, A> GroupPatchCall<'a, C, A> where C: BorrowMut, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Group)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17214,11 +17435,20 @@ impl<'a, C, A> GroupPatchCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17241,7 +17471,7 @@ impl<'a, C, A> GroupPatchCall<'a, C, A> where C: BorrowMut, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -17422,6 +17652,7 @@ impl<'a, C, A> GroupUpdateCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Group)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17477,11 +17708,20 @@ impl<'a, C, A> GroupUpdateCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17504,7 +17744,7 @@ impl<'a, C, A> GroupUpdateCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -17732,7 +17972,7 @@ impl<'a, C, A> GroupDeleteCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17754,7 +17994,7 @@ impl<'a, C, A> GroupDeleteCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -17913,6 +18153,7 @@ impl<'a, C, A> GroupAliaseInsertCall<'a, C, A> where C: BorrowMut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Alias)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17968,11 +18209,20 @@ impl<'a, C, A> GroupAliaseInsertCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17995,7 +18245,7 @@ impl<'a, C, A> GroupAliaseInsertCall<'a, C, A> where C: BorrowMut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -18225,7 +18475,7 @@ impl<'a, C, A> GroupAliaseDeleteCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18247,7 +18497,7 @@ impl<'a, C, A> GroupAliaseDeleteCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -18415,6 +18665,7 @@ impl<'a, C, A> GroupInsertCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Group)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -18445,11 +18696,20 @@ impl<'a, C, A> GroupInsertCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -18472,7 +18732,7 @@ impl<'a, C, A> GroupInsertCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -18692,7 +18952,7 @@ impl<'a, C, A> AspDeleteCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18714,7 +18974,7 @@ impl<'a, C, A> AspDeleteCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -18931,7 +19191,7 @@ impl<'a, C, A> AspListCall<'a, C, A> where C: BorrowMut, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18953,7 +19213,7 @@ impl<'a, C, A> AspListCall<'a, C, A> where C: BorrowMut, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -19172,7 +19432,7 @@ impl<'a, C, A> AspGetCall<'a, C, A> where C: BorrowMut, A: oauth2 if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19194,7 +19454,7 @@ impl<'a, C, A> AspGetCall<'a, C, A> where C: BorrowMut, A: oauth2 access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -19421,7 +19681,7 @@ impl<'a, C, A> SchemaListCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19443,7 +19703,7 @@ impl<'a, C, A> SchemaListCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -19662,7 +19922,7 @@ impl<'a, C, A> SchemaGetCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19684,7 +19944,7 @@ impl<'a, C, A> SchemaGetCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -19864,6 +20124,7 @@ impl<'a, C, A> SchemaPatchCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Schema)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -19920,11 +20181,20 @@ impl<'a, C, A> SchemaPatchCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -19947,7 +20217,7 @@ impl<'a, C, A> SchemaPatchCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -20138,6 +20408,7 @@ impl<'a, C, A> SchemaInsertCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Schema)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -20193,11 +20464,20 @@ impl<'a, C, A> SchemaInsertCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -20220,7 +20500,7 @@ impl<'a, C, A> SchemaInsertCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -20450,7 +20730,7 @@ impl<'a, C, A> SchemaDeleteCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -20472,7 +20752,7 @@ impl<'a, C, A> SchemaDeleteCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -20642,6 +20922,7 @@ impl<'a, C, A> SchemaUpdateCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Schema)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -20698,11 +20979,20 @@ impl<'a, C, A> SchemaUpdateCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -20725,7 +21015,7 @@ impl<'a, C, A> SchemaUpdateCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) diff --git a/gen/admin1_reports-cli/Cargo.toml b/gen/admin1_reports-cli/Cargo.toml index 7e14157d2f..3fef49ff48 100644 --- a/gen/admin1_reports-cli/Cargo.toml +++ b/gen/admin1_reports-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-admin1_reports-cli" -version = "0.1.0+20150115" +version = "0.2.0+20150115" authors = ["Sebastian Thiel "] description = "A complete library to interact with reports (protocol reports_v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/admin1_reports-cli" @@ -17,15 +17,14 @@ keywords = ["admin", "google", "cli"] name = "admin1-reports" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-admin1_reports] path = "../admin1_reports" diff --git a/gen/admin1_reports-cli/README.md b/gen/admin1_reports-cli/README.md index 887753e972..489de951c6 100644 --- a/gen/admin1_reports-cli/README.md +++ b/gen/admin1_reports-cli/README.md @@ -10,25 +10,30 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *reports* API can be found at the +[official documentation site](https://developers.google.com/admin-sdk/reports/). + # Usage -This documentation was generated from the *reports* API at revision *20150115*. The CLI is at version *0.1.0*. +This documentation was generated from the *reports* API at revision *20150115*. The CLI is at version *0.2.0*. ```bash - admin1-reports [options] activities list [-p ...] [-o ] - admin1-reports [options] activities watch -r ... [-p ...] [-o ] - admin1-reports [options] channels stop -r ... [-p ...] - admin1-reports [options] customer-usage-reports get [-p ...] [-o ] - admin1-reports [options] user-usage-report get [-p ...] [-o ] +admin1-reports [options] + activities + list [-p ]... [-o ] + watch (-r )... [-p ]... [-o ] + channels + stop (-r )... [-p ]... + customer-usage-reports + get [-p ]... [-o ] + user-usage-report + get [-p ]... [-o ] admin1-reports --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_admin1_reports_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/admin1_reports-cli/mkdocs.yml b/gen/admin1_reports-cli/mkdocs.yml index 5938a8b69f..2b76943f3e 100644 --- a/gen/admin1_reports-cli/mkdocs.yml +++ b/gen/admin1_reports-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: reports v0.1.0+20150115 +site_name: reports v0.2.0+20150115 site_url: http://byron.github.io/google-apis-rs/google-admin1_reports-cli site_description: Write integrating applications with bcore diff --git a/gen/admin1_reports-cli/src/cmn.rs b/gen/admin1_reports-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/admin1_reports-cli/src/cmn.rs +++ b/gen/admin1_reports-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/admin1_reports-cli/src/main.rs b/gen/admin1_reports-cli/src/main.rs index e5669a54ab..45b80976f2 100644 --- a/gen/admin1_reports-cli/src/main.rs +++ b/gen/admin1_reports-cli/src/main.rs @@ -2,71 +2,53 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_admin1_reports as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - admin1-reports [options] activities list [-p ...] [-o ] - admin1-reports [options] activities watch -r ... [-p ...] [-o ] - admin1-reports [options] channels stop -r ... [-p ...] - admin1-reports [options] customer-usage-reports get [-p ...] [-o ] - admin1-reports [options] user-usage-report get [-p ...] [-o ] - admin1-reports --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_admin1_reports_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Reports>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _activities_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.activities().list(&self.opt.arg_user_key, &self.opt.arg_application_name); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _activities_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.activities().list(opt.value_of("user-key").unwrap_or(""), opt.value_of("application-name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-time" => { @@ -93,52 +75,56 @@ impl Engine { "actor-ip-address" => { call = call.actor_ip_address(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-time", "actor-ip-address", "max-results", "event-name", "page-token", "filters", "end-time", "customer-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _activities_watch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _activities_watch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Channel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -188,12 +174,13 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.activities().watch(request, &self.opt.arg_user_key, &self.opt.arg_application_name); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.activities().watch(request, opt.value_of("user-key").unwrap_or(""), opt.value_of("application-name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-time" => { @@ -220,52 +207,56 @@ impl Engine { "actor-ip-address" => { call = call.actor_ip_address(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-time", "actor-ip-address", "max-results", "event-name", "page-token", "filters", "end-time", "customer-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _channels_stop(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _channels_stop(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Channel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -315,56 +306,56 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.channels().stop(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _customer_usage_reports_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.customer_usage_reports().get(&self.opt.arg_date); - for parg in self.opt.arg_v.iter() { + fn _customer_usage_reports_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.customer_usage_reports().get(opt.value_of("date").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "parameters" => { @@ -376,50 +367,54 @@ impl Engine { "customer-id" => { call = call.customer_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "customer-id", "parameters"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _user_usage_report_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.user_usage_report().get(&self.opt.arg_user_key, &self.opt.arg_date); - for parg in self.opt.arg_v.iter() { + fn _user_usage_report_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.user_usage_report().get(opt.value_of("user-key").unwrap_or(""), opt.value_of("date").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "parameters" => { @@ -437,96 +432,122 @@ impl Engine { "customer-id" => { call = call.customer_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "filters", "max-results", "parameters", "customer-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_activities { - if self.opt.cmd_list { - call_result = self._activities_list(dry_run, &mut err); - } else if self.opt.cmd_watch { - call_result = self._activities_watch(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("activities", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._activities_list(opt, dry_run, &mut err); + }, + ("watch", Some(opt)) => { + call_result = self._activities_watch(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("activities".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("channels", Some(opt)) => { + match opt.subcommand() { + ("stop", Some(opt)) => { + call_result = self._channels_stop(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("channels".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("customer-usage-reports", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._customer_usage_reports_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("customer-usage-reports".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("user-usage-report", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._user_usage_report_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("user-usage-report".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_channels { - if self.opt.cmd_stop { - call_result = self._channels_stop(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_customer_usage_reports { - if self.opt.cmd_get { - call_result = self._customer_usage_reports_get(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_user_usage_report { - if self.opt.cmd_get { - call_result = self._user_usage_report_get(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -539,7 +560,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -552,7 +573,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -562,37 +583,263 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Reports::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("activities", "methods: 'list' and 'watch'", vec![ + ("list", + Some(r##"Retrieves a list of activities for a specific customer and application."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_reports_cli/activities_list", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Represents the profile id or the user email for which the data should be filtered. When 'all' is specified as the userKey, it returns usageReports for all users."##), + Some(true), + Some(false)), + + (Some(r##"application-name"##), + None, + Some(r##"Application name for which the events are to be retrieved."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("watch", + Some(r##"Push changes to activities"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_reports_cli/activities_watch", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Represents the profile id or the user email for which the data should be filtered. When 'all' is specified as the userKey, it returns usageReports for all users."##), + Some(true), + Some(false)), + + (Some(r##"application-name"##), + None, + Some(r##"Application name for which the events are to be retrieved."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("channels", "methods: 'stop'", vec![ + ("stop", + Some(r##"Stop watching resources through this channel"##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_reports_cli/channels_stop", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("customer-usage-reports", "methods: 'get'", vec![ + ("get", + Some(r##"Retrieves a report which is a collection of properties / statistics for a specific customer."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_reports_cli/customer-usage-reports_get", + vec![ + (Some(r##"date"##), + None, + Some(r##"Represents the date in yyyy-mm-dd format for which the data is to be fetched."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("user-usage-report", "methods: 'get'", vec![ + ("get", + Some(r##"Retrieves a report which is a collection of properties / statistics for a set of users."##), + "Details at http://byron.github.io/google-apis-rs/google_admin1_reports_cli/user-usage-report_get", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"Represents the profile id or the user email for which the data should be filtered."##), + Some(true), + Some(false)), + + (Some(r##"date"##), + None, + Some(r##"Represents the date in yyyy-mm-dd format for which the data is to be fetched."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("admin1-reports") + .author("Sebastian Thiel ") + .version("0.2.0+20150115") + .about("Allows the administrators of Google Apps customers to fetch reports about the usage, collaboration, security and risk for their users.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_admin1_reports_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/admin1_reports/Cargo.toml b/gen/admin1_reports/Cargo.toml index b425c525c5..a32b68000f 100644 --- a/gen/admin1_reports/Cargo.toml +++ b/gen/admin1_reports/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-admin1_reports" -version = "0.1.6+20150115" +version = "0.1.7+20150115" authors = ["Sebastian Thiel "] description = "A complete library to interact with reports (protocol reports_v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/admin1_reports" @@ -15,9 +15,10 @@ keywords = ["admin", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/admin1_reports/README.md b/gen/admin1_reports/README.md index 2095a006ee..d3c434f4a4 100644 --- a/gen/admin1_reports/README.md +++ b/gen/admin1_reports/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-admin1_reports` library allows access to all features of the *Google reports* service. -This documentation was generated from *reports* crate version *0.1.6+20150115*, where *20150115* is the exact revision of the *admin:reports_v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *reports* crate version *0.1.7+20150115*, where *20150115* is the exact revision of the *admin:reports_v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *reports* *v1_reports* API can be found at the [official documentation site](https://developers.google.com/admin-sdk/reports/). @@ -183,7 +183,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_admin1_reports/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_admin1_reports/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/admin1_reports/src/cmn.rs b/gen/admin1_reports/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/admin1_reports/src/cmn.rs +++ b/gen/admin1_reports/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/admin1_reports/src/lib.rs b/gen/admin1_reports/src/lib.rs index 10bcc6ff2b..58a3e8c8f1 100644 --- a/gen/admin1_reports/src/lib.rs +++ b/gen/admin1_reports/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *reports* crate version *0.1.6+20150115*, where *20150115* is the exact revision of the *admin:reports_v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *reports* crate version *0.1.7+20150115*, where *20150115* is the exact revision of the *admin:reports_v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *reports* *v1_reports* API can be found at the //! [official documentation site](https://developers.google.com/admin-sdk/reports/). @@ -184,7 +184,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -193,7 +193,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -209,6 +208,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -343,7 +343,7 @@ impl<'a, C, A> Reports Reports { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -361,7 +361,7 @@ impl<'a, C, A> Reports } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1043,6 +1043,7 @@ impl<'a, C, A> ChannelStopCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1072,11 +1073,20 @@ impl<'a, C, A> ChannelStopCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1099,7 +1109,7 @@ impl<'a, C, A> ChannelStopCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1277,6 +1287,7 @@ impl<'a, C, A> ActivityWatchCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Channel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1357,11 +1368,20 @@ impl<'a, C, A> ActivityWatchCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1384,7 +1404,7 @@ impl<'a, C, A> ActivityWatchCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1721,7 +1741,7 @@ impl<'a, C, A> ActivityListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1743,7 +1763,7 @@ impl<'a, C, A> ActivityListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2041,7 +2061,7 @@ impl<'a, C, A> CustomerUsageReportGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2063,7 +2083,7 @@ impl<'a, C, A> CustomerUsageReportGetCall<'a, C, A> where C: BorrowMut UserUsageReportGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2350,7 +2370,7 @@ impl<'a, C, A> UserUsageReportGetCall<'a, C, A> where C: BorrowMut"] description = "A complete library to interact with admin (protocol email_migration_v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/admin2_email_migration-cli" @@ -17,15 +17,14 @@ keywords = ["admin", "google", "cli"] name = "admin2-email-migration" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-admin2_email_migration] path = "../admin2_email_migration" diff --git a/gen/admin2_email_migration-cli/README.md b/gen/admin2_email_migration-cli/README.md index 351436dc4b..7c764df59a 100644 --- a/gen/admin2_email_migration-cli/README.md +++ b/gen/admin2_email_migration-cli/README.md @@ -10,21 +10,23 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *admin* API can be found at the +[official documentation site](https://developers.google.com/admin-sdk/email-migration/v2/). + # Usage -This documentation was generated from the *admin* API at revision *20150303*. The CLI is at version *0.1.0*. +This documentation was generated from the *admin* API at revision *20150303*. The CLI is at version *0.2.0*. ```bash - admin2-email-migration [options] mail insert -r ... -u (simple|resumable) [-p ...] +admin2-email-migration [options] + mail + insert (-r )... (-u (simple|resumable) -f [-m ]) [-p ]... admin2-email-migration --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_admin2_email_migration_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/admin2_email_migration-cli/mkdocs.yml b/gen/admin2_email_migration-cli/mkdocs.yml index d307c18147..59760a08a6 100644 --- a/gen/admin2_email_migration-cli/mkdocs.yml +++ b/gen/admin2_email_migration-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: admin v0.1.0+20150303 +site_name: admin v0.2.0+20150303 site_url: http://byron.github.io/google-apis-rs/google-admin2_email_migration-cli site_description: Write integrating applications with bcore diff --git a/gen/admin2_email_migration-cli/src/cmn.rs b/gen/admin2_email_migration-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/admin2_email_migration-cli/src/cmn.rs +++ b/gen/admin2_email_migration-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/admin2_email_migration-cli/src/main.rs b/gen/admin2_email_migration-cli/src/main.rs index 14e5747a4b..4e556eaac5 100644 --- a/gen/admin2_email_migration-cli/src/main.rs +++ b/gen/admin2_email_migration-cli/src/main.rs @@ -2,69 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_admin2_email_migration as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - admin2-email-migration [options] mail insert -r ... -u (simple|resumable) [-p ...] - admin2-email-migration --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_admin2_email_migration_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Admin>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _mail_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { +impl<'n, 'a> Engine<'n, 'a> { + fn _mail_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::MailItem::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -110,89 +96,92 @@ impl Engine { request.is_deleted = Some(arg_from_str(value.unwrap_or("false"), err, "is-deleted", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["is-deleted", "is-draft", "is-inbox", "is-sent", "is-starred", "is-trash", "is-unread", "kind", "labels"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.mail().insert(request, &self.opt.arg_user_key); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.mail().insert(request, opt.value_of("user-key").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() - }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_mail { - if self.opt.cmd_insert { - call_result = self._mail_insert(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("mail", Some(opt)) => { + match opt.subcommand() { + ("insert", Some(opt)) => { + call_result = self._mail_insert(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("mail".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -205,7 +194,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -218,7 +207,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -228,37 +217,166 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Admin::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let upload_value_names = ["mode", "file"]; + let arg_data = [ + ("mail", "methods: 'insert'", vec![ + ("insert", + Some(r##"Insert Mail into Google's Gmail backends"##), + "Details at http://byron.github.io/google-apis-rs/google_admin2_email_migration_cli/mail_insert", + vec![ + (Some(r##"user-key"##), + None, + Some(r##"The email or immutable id of the user"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ]; + + let mut app = App::new("admin2-email-migration") + .author("Sebastian Thiel ") + .version("0.2.0+20150303") + .about("Email Migration API lets you migrate emails of users to Google backends.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_admin2_email_migration_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + if arg_name_str == "mode" { + arg = arg.number_of_values(2); + arg = arg.value_names(&upload_value_names); + + scmd = scmd.arg(Arg::with_name("mime") + .short("m") + .requires("mode") + .required(false) + .help("The file's mime time, like 'application/octet-stream'") + .takes_value(true)); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/admin2_email_migration/Cargo.toml b/gen/admin2_email_migration/Cargo.toml index 0822931c86..add281611d 100644 --- a/gen/admin2_email_migration/Cargo.toml +++ b/gen/admin2_email_migration/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-admin2_email_migration" -version = "0.1.6+20150303" +version = "0.1.7+20150303" authors = ["Sebastian Thiel "] description = "A complete library to interact with admin (protocol email_migration_v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/admin2_email_migration" @@ -15,9 +15,10 @@ keywords = ["admin", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/admin2_email_migration/README.md b/gen/admin2_email_migration/README.md index a51924c4ab..d16e87564e 100644 --- a/gen/admin2_email_migration/README.md +++ b/gen/admin2_email_migration/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-admin2_email_migration` library allows access to all features of the *Google admin* service. -This documentation was generated from *admin* crate version *0.1.6+20150303*, where *20150303* is the exact revision of the *admin:email_migration_v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *admin* crate version *0.1.7+20150303*, where *20150303* is the exact revision of the *admin:email_migration_v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *admin* *v2_email_migration* API can be found at the [official documentation site](https://developers.google.com/admin-sdk/email-migration/v2/). @@ -168,7 +168,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_admin2_email_migration/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_admin2_email_migration/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/admin2_email_migration/src/cmn.rs b/gen/admin2_email_migration/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/admin2_email_migration/src/cmn.rs +++ b/gen/admin2_email_migration/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/admin2_email_migration/src/lib.rs b/gen/admin2_email_migration/src/lib.rs index 642f00bc00..0a0d37e215 100644 --- a/gen/admin2_email_migration/src/lib.rs +++ b/gen/admin2_email_migration/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *admin* crate version *0.1.6+20150303*, where *20150303* is the exact revision of the *admin:email_migration_v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *admin* crate version *0.1.7+20150303*, where *20150303* is the exact revision of the *admin:email_migration_v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *admin* *v2_email_migration* API can be found at the //! [official documentation site](https://developers.google.com/admin-sdk/email-migration/v2/). @@ -169,7 +169,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -178,7 +178,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -194,6 +193,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -317,7 +317,7 @@ impl<'a, C, A> Admin Admin { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -326,7 +326,7 @@ impl<'a, C, A> Admin } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -508,6 +508,7 @@ impl<'a, C, A> MailInsertCall<'a, C, A> where C: BorrowMut, A: oa /// Perform the operation you have build so far. fn doit(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -570,11 +571,20 @@ impl<'a, C, A> MailInsertCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -629,7 +639,7 @@ impl<'a, C, A> MailInsertCall<'a, C, A> where C: BorrowMut, A: oa _ => (&mut request_value_reader as &mut io::Read, ContentType(json_mime_type.clone())), }; let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(content_type) @@ -679,7 +689,7 @@ impl<'a, C, A> MailInsertCall<'a, C, A> where C: BorrowMut, A: oa let upload_result = { let url_str = &res.headers.get::().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -707,6 +717,7 @@ impl<'a, C, A> MailInsertCall<'a, C, A> where C: BorrowMut, A: oa Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } diff --git a/gen/adsense1d4-cli/Cargo.toml b/gen/adsense1d4-cli/Cargo.toml index 7538769d4e..4b7d77a6b4 100644 --- a/gen/adsense1d4-cli/Cargo.toml +++ b/gen/adsense1d4-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-adsense1d4-cli" -version = "0.1.0+20150326" +version = "0.2.0+20150326" authors = ["Sebastian Thiel "] description = "A complete library to interact with AdSense (protocol v1.4)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/adsense1d4-cli" @@ -17,15 +17,14 @@ keywords = ["adsense", "google", "cli"] name = "adsense1d4" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-adsense1d4] path = "../adsense1d4" diff --git a/gen/adsense1d4-cli/README.md b/gen/adsense1d4-cli/README.md index c12646f482..9429cfc79d 100644 --- a/gen/adsense1d4-cli/README.md +++ b/gen/adsense1d4-cli/README.md @@ -10,58 +10,69 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *AdSense* API can be found at the +[official documentation site](https://developers.google.com/adsense/management/). + # Usage -This documentation was generated from the *AdSense* API at revision *20150326*. The CLI is at version *0.1.0*. +This documentation was generated from the *AdSense* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - adsense1d4 [options] accounts adclients-list [-p ...] [-o ] - adsense1d4 [options] accounts adunits-customchannels-list [-p ...] [-o ] - adsense1d4 [options] accounts adunits-get [-p ...] [-o ] - adsense1d4 [options] accounts adunits-get-ad-code [-p ...] [-o ] - adsense1d4 [options] accounts adunits-list [-p ...] [-o ] - adsense1d4 [options] accounts alerts-delete [-p ...] - adsense1d4 [options] accounts alerts-list [-p ...] [-o ] - adsense1d4 [options] accounts customchannels-adunits-list [-p ...] [-o ] - adsense1d4 [options] accounts customchannels-get [-p ...] [-o ] - adsense1d4 [options] accounts customchannels-list [-p ...] [-o ] - adsense1d4 [options] accounts get [-p ...] [-o ] - adsense1d4 [options] accounts list [-p ...] [-o ] - adsense1d4 [options] accounts payments-list [-p ...] [-o ] - adsense1d4 [options] accounts reports-generate [-p ...] [-o ] - adsense1d4 [options] accounts reports-saved-generate [-p ...] [-o ] - adsense1d4 [options] accounts reports-saved-list [-p ...] [-o ] - adsense1d4 [options] accounts savedadstyles-get [-p ...] [-o ] - adsense1d4 [options] accounts savedadstyles-list [-p ...] [-o ] - adsense1d4 [options] accounts urlchannels-list [-p ...] [-o ] - adsense1d4 [options] adclients list [-p ...] [-o ] - adsense1d4 [options] adunits customchannels-list [-p ...] [-o ] - adsense1d4 [options] adunits get [-p ...] [-o ] - adsense1d4 [options] adunits get-ad-code [-p ...] [-o ] - adsense1d4 [options] adunits list [-p ...] [-o ] - adsense1d4 [options] alerts delete [-p ...] - adsense1d4 [options] alerts list [-p ...] [-o ] - adsense1d4 [options] customchannels adunits-list [-p ...] [-o ] - adsense1d4 [options] customchannels get [-p ...] [-o ] - adsense1d4 [options] customchannels list [-p ...] [-o ] - adsense1d4 [options] metadata dimensions-list [-p ...] [-o ] - adsense1d4 [options] metadata metrics-list [-p ...] [-o ] - adsense1d4 [options] payments list [-p ...] [-o ] - adsense1d4 [options] reports generate [-p ...] [-o ] - adsense1d4 [options] reports saved-generate [-p ...] [-o ] - adsense1d4 [options] reports saved-list [-p ...] [-o ] - adsense1d4 [options] savedadstyles get [-p ...] [-o ] - adsense1d4 [options] savedadstyles list [-p ...] [-o ] - adsense1d4 [options] urlchannels list [-p ...] [-o ] +adsense1d4 [options] + accounts + adclients-list [-p ]... [-o ] + adunits-customchannels-list [-p ]... [-o ] + adunits-get [-p ]... [-o ] + adunits-get-ad-code [-p ]... [-o ] + adunits-list [-p ]... [-o ] + alerts-delete [-p ]... + alerts-list [-p ]... [-o ] + customchannels-adunits-list [-p ]... [-o ] + customchannels-get [-p ]... [-o ] + customchannels-list [-p ]... [-o ] + get [-p ]... [-o ] + list [-p ]... [-o ] + payments-list [-p ]... [-o ] + reports-generate [-p ]... [-o ] + reports-saved-generate [-p ]... [-o ] + reports-saved-list [-p ]... [-o ] + savedadstyles-get [-p ]... [-o ] + savedadstyles-list [-p ]... [-o ] + urlchannels-list [-p ]... [-o ] + adclients + list [-p ]... [-o ] + adunits + customchannels-list [-p ]... [-o ] + get [-p ]... [-o ] + get-ad-code [-p ]... [-o ] + list [-p ]... [-o ] + alerts + delete [-p ]... + list [-p ]... [-o ] + customchannels + adunits-list [-p ]... [-o ] + get [-p ]... [-o ] + list [-p ]... [-o ] + metadata + dimensions-list [-p ]... [-o ] + metrics-list [-p ]... [-o ] + payments + list [-p ]... [-o ] + reports + generate [-p ]... [-o ] + saved-generate [-p ]... [-o ] + saved-list [-p ]... [-o ] + savedadstyles + get [-p ]... [-o ] + list [-p ]... [-o ] + urlchannels + list [-p ]... [-o ] adsense1d4 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_adsense1d4_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/adsense1d4-cli/mkdocs.yml b/gen/adsense1d4-cli/mkdocs.yml index 5cae7da908..c20bd075f8 100644 --- a/gen/adsense1d4-cli/mkdocs.yml +++ b/gen/adsense1d4-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: AdSense v0.1.0+20150326 +site_name: AdSense v0.2.0+20150326 site_url: http://byron.github.io/google-apis-rs/google-adsense1d4-cli site_description: Write integrating applications with bcore diff --git a/gen/adsense1d4-cli/src/cmn.rs b/gen/adsense1d4-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/adsense1d4-cli/src/cmn.rs +++ b/gen/adsense1d4-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/adsense1d4-cli/src/main.rs b/gen/adsense1d4-cli/src/main.rs index 413efdcdce..bba8da7541 100644 --- a/gen/adsense1d4-cli/src/main.rs +++ b/gen/adsense1d4-cli/src/main.rs @@ -2,104 +2,53 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_adsense1d4 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - adsense1d4 [options] accounts adclients-list [-p ...] [-o ] - adsense1d4 [options] accounts adunits-customchannels-list [-p ...] [-o ] - adsense1d4 [options] accounts adunits-get [-p ...] [-o ] - adsense1d4 [options] accounts adunits-get-ad-code [-p ...] [-o ] - adsense1d4 [options] accounts adunits-list [-p ...] [-o ] - adsense1d4 [options] accounts alerts-delete [-p ...] - adsense1d4 [options] accounts alerts-list [-p ...] [-o ] - adsense1d4 [options] accounts customchannels-adunits-list [-p ...] [-o ] - adsense1d4 [options] accounts customchannels-get [-p ...] [-o ] - adsense1d4 [options] accounts customchannels-list [-p ...] [-o ] - adsense1d4 [options] accounts get [-p ...] [-o ] - adsense1d4 [options] accounts list [-p ...] [-o ] - adsense1d4 [options] accounts payments-list [-p ...] [-o ] - adsense1d4 [options] accounts reports-generate [-p ...] [-o ] - adsense1d4 [options] accounts reports-saved-generate [-p ...] [-o ] - adsense1d4 [options] accounts reports-saved-list [-p ...] [-o ] - adsense1d4 [options] accounts savedadstyles-get [-p ...] [-o ] - adsense1d4 [options] accounts savedadstyles-list [-p ...] [-o ] - adsense1d4 [options] accounts urlchannels-list [-p ...] [-o ] - adsense1d4 [options] adclients list [-p ...] [-o ] - adsense1d4 [options] adunits customchannels-list [-p ...] [-o ] - adsense1d4 [options] adunits get [-p ...] [-o ] - adsense1d4 [options] adunits get-ad-code [-p ...] [-o ] - adsense1d4 [options] adunits list [-p ...] [-o ] - adsense1d4 [options] alerts delete [-p ...] - adsense1d4 [options] alerts list [-p ...] [-o ] - adsense1d4 [options] customchannels adunits-list [-p ...] [-o ] - adsense1d4 [options] customchannels get [-p ...] [-o ] - adsense1d4 [options] customchannels list [-p ...] [-o ] - adsense1d4 [options] metadata dimensions-list [-p ...] [-o ] - adsense1d4 [options] metadata metrics-list [-p ...] [-o ] - adsense1d4 [options] payments list [-p ...] [-o ] - adsense1d4 [options] reports generate [-p ...] [-o ] - adsense1d4 [options] reports saved-generate [-p ...] [-o ] - adsense1d4 [options] reports saved-list [-p ...] [-o ] - adsense1d4 [options] savedadstyles get [-p ...] [-o ] - adsense1d4 [options] savedadstyles list [-p ...] [-o ] - adsense1d4 [options] urlchannels list [-p ...] [-o ] - adsense1d4 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_adsense1d4_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::AdSense>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _accounts_adclients_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().adclients_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _accounts_adclients_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().adclients_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -108,50 +57,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_adunits_customchannels_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().adunits_customchannels_list(&self.opt.arg_account_id, &self.opt.arg_ad_client_id, &self.opt.arg_ad_unit_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_adunits_customchannels_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().adunits_customchannels_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("ad-unit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -160,142 +113,154 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_adunits_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().adunits_get(&self.opt.arg_account_id, &self.opt.arg_ad_client_id, &self.opt.arg_ad_unit_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_adunits_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().adunits_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("ad-unit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_adunits_get_ad_code(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().adunits_get_ad_code(&self.opt.arg_account_id, &self.opt.arg_ad_client_id, &self.opt.arg_ad_unit_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_adunits_get_ad_code(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().adunits_get_ad_code(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("ad-unit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_adunits_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().adunits_list(&self.opt.arg_account_id, &self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_adunits_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().adunits_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -307,143 +272,150 @@ impl Engine { "include-inactive" => { call = call.include_inactive(arg_from_str(value.unwrap_or("false"), err, "include-inactive", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["include-inactive", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_alerts_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().alerts_delete(&self.opt.arg_account_id, &self.opt.arg_alert_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_alerts_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().alerts_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("alert-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _accounts_alerts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().alerts_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_alerts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().alerts_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "locale" => { call = call.locale(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_customchannels_adunits_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().customchannels_adunits_list(&self.opt.arg_account_id, &self.opt.arg_ad_client_id, &self.opt.arg_custom_channel_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_customchannels_adunits_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().customchannels_adunits_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("custom-channel-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -455,96 +427,104 @@ impl Engine { "include-inactive" => { call = call.include_inactive(arg_from_str(value.unwrap_or("false"), err, "include-inactive", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["include-inactive", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_customchannels_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().customchannels_get(&self.opt.arg_account_id, &self.opt.arg_ad_client_id, &self.opt.arg_custom_channel_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_customchannels_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().customchannels_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("custom-channel-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_customchannels_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().customchannels_list(&self.opt.arg_account_id, &self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_customchannels_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().customchannels_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -553,99 +533,107 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().get(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().get(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "tree" => { call = call.tree(arg_from_str(value.unwrap_or("false"), err, "tree", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["tree"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.accounts().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -654,97 +642,105 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_payments_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().payments_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_payments_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().payments_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_reports_generate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounts_reports_generate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut download_mode = false; - let mut call = self.hub.accounts().reports_generate(&self.opt.arg_account_id, &self.opt.arg_start_date, &self.opt.arg_end_date); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().reports_generate(opt.value_of("account-id").unwrap_or(""), opt.value_of("start-date").unwrap_or(""), opt.value_of("end-date").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "use-timezone-reporting" => { @@ -774,57 +770,61 @@ impl Engine { "currency" => { call = call.currency(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sort", "locale", "metric", "max-results", "filter", "currency", "start-index", "use-timezone-reporting", "dimension"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { if !download_mode { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); } else { io::copy(&mut response, &mut ostream).unwrap(); } - None + Ok(()) } } } } - fn _accounts_reports_saved_generate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().reports_saved_generate(&self.opt.arg_account_id, &self.opt.arg_saved_report_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_reports_saved_generate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().reports_saved_generate(opt.value_of("account-id").unwrap_or(""), opt.value_of("saved-report-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -836,50 +836,54 @@ impl Engine { "locale" => { call = call.locale(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale", "start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_reports_saved_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().reports_saved_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_reports_saved_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().reports_saved_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -888,96 +892,104 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_savedadstyles_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().savedadstyles_get(&self.opt.arg_account_id, &self.opt.arg_saved_ad_style_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_savedadstyles_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().savedadstyles_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("saved-ad-style-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_savedadstyles_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().savedadstyles_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_savedadstyles_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().savedadstyles_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -986,50 +998,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_urlchannels_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().urlchannels_list(&self.opt.arg_account_id, &self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_urlchannels_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().urlchannels_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1038,50 +1054,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _adclients_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _adclients_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.adclients().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1090,50 +1110,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _adunits_customchannels_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.adunits().customchannels_list(&self.opt.arg_ad_client_id, &self.opt.arg_ad_unit_id); - for parg in self.opt.arg_v.iter() { + fn _adunits_customchannels_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.adunits().customchannels_list(opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("ad-unit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1142,142 +1166,154 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _adunits_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.adunits().get(&self.opt.arg_ad_client_id, &self.opt.arg_ad_unit_id); - for parg in self.opt.arg_v.iter() { + fn _adunits_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.adunits().get(opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("ad-unit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _adunits_get_ad_code(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.adunits().get_ad_code(&self.opt.arg_ad_client_id, &self.opt.arg_ad_unit_id); - for parg in self.opt.arg_v.iter() { + fn _adunits_get_ad_code(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.adunits().get_ad_code(opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("ad-unit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _adunits_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.adunits().list(&self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + fn _adunits_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.adunits().list(opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1289,143 +1325,150 @@ impl Engine { "include-inactive" => { call = call.include_inactive(arg_from_str(value.unwrap_or("false"), err, "include-inactive", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["include-inactive", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _alerts_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.alerts().delete(&self.opt.arg_alert_id); - for parg in self.opt.arg_v.iter() { + fn _alerts_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.alerts().delete(opt.value_of("alert-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _alerts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _alerts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.alerts().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "locale" => { call = call.locale(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _customchannels_adunits_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.customchannels().adunits_list(&self.opt.arg_ad_client_id, &self.opt.arg_custom_channel_id); - for parg in self.opt.arg_v.iter() { + fn _customchannels_adunits_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.customchannels().adunits_list(opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("custom-channel-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1437,96 +1480,104 @@ impl Engine { "include-inactive" => { call = call.include_inactive(arg_from_str(value.unwrap_or("false"), err, "include-inactive", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["include-inactive", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _customchannels_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.customchannels().get(&self.opt.arg_ad_client_id, &self.opt.arg_custom_channel_id); - for parg in self.opt.arg_v.iter() { + fn _customchannels_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.customchannels().get(opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("custom-channel-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _customchannels_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.customchannels().list(&self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + fn _customchannels_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.customchannels().list(opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1535,189 +1586,205 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _metadata_dimensions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _metadata_dimensions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.metadata().dimensions_list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _metadata_metrics_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _metadata_metrics_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.metadata().metrics_list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _payments_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _payments_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.payments().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _reports_generate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _reports_generate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut download_mode = false; - let mut call = self.hub.reports().generate(&self.opt.arg_start_date, &self.opt.arg_end_date); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.reports().generate(opt.value_of("start-date").unwrap_or(""), opt.value_of("end-date").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "use-timezone-reporting" => { @@ -1750,57 +1817,61 @@ impl Engine { "account-id" => { call = call.add_account_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sort", "locale", "metric", "max-results", "filter", "currency", "start-index", "use-timezone-reporting", "dimension", "account-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { if !download_mode { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); } else { io::copy(&mut response, &mut ostream).unwrap(); } - None + Ok(()) } } } } - fn _reports_saved_generate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.reports().saved_generate(&self.opt.arg_saved_report_id); - for parg in self.opt.arg_v.iter() { + fn _reports_saved_generate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.reports().saved_generate(opt.value_of("saved-report-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -1812,50 +1883,54 @@ impl Engine { "locale" => { call = call.locale(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale", "start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _reports_saved_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _reports_saved_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.reports().saved_list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1864,96 +1939,104 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _savedadstyles_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.savedadstyles().get(&self.opt.arg_saved_ad_style_id); - for parg in self.opt.arg_v.iter() { + fn _savedadstyles_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.savedadstyles().get(opt.value_of("saved-ad-style-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _savedadstyles_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _savedadstyles_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.savedadstyles().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1962,50 +2045,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _urlchannels_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.urlchannels().list(&self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + fn _urlchannels_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.urlchannels().list(opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2014,192 +2101,269 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_accounts { - if self.opt.cmd_adclients_list { - call_result = self._accounts_adclients_list(dry_run, &mut err); - } else if self.opt.cmd_adunits_customchannels_list { - call_result = self._accounts_adunits_customchannels_list(dry_run, &mut err); - } else if self.opt.cmd_adunits_get { - call_result = self._accounts_adunits_get(dry_run, &mut err); - } else if self.opt.cmd_adunits_get_ad_code { - call_result = self._accounts_adunits_get_ad_code(dry_run, &mut err); - } else if self.opt.cmd_adunits_list { - call_result = self._accounts_adunits_list(dry_run, &mut err); - } else if self.opt.cmd_alerts_delete { - call_result = self._accounts_alerts_delete(dry_run, &mut err); - } else if self.opt.cmd_alerts_list { - call_result = self._accounts_alerts_list(dry_run, &mut err); - } else if self.opt.cmd_customchannels_adunits_list { - call_result = self._accounts_customchannels_adunits_list(dry_run, &mut err); - } else if self.opt.cmd_customchannels_get { - call_result = self._accounts_customchannels_get(dry_run, &mut err); - } else if self.opt.cmd_customchannels_list { - call_result = self._accounts_customchannels_list(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._accounts_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._accounts_list(dry_run, &mut err); - } else if self.opt.cmd_payments_list { - call_result = self._accounts_payments_list(dry_run, &mut err); - } else if self.opt.cmd_reports_generate { - call_result = self._accounts_reports_generate(dry_run, &mut err); - } else if self.opt.cmd_reports_saved_generate { - call_result = self._accounts_reports_saved_generate(dry_run, &mut err); - } else if self.opt.cmd_reports_saved_list { - call_result = self._accounts_reports_saved_list(dry_run, &mut err); - } else if self.opt.cmd_savedadstyles_get { - call_result = self._accounts_savedadstyles_get(dry_run, &mut err); - } else if self.opt.cmd_savedadstyles_list { - call_result = self._accounts_savedadstyles_list(dry_run, &mut err); - } else if self.opt.cmd_urlchannels_list { - call_result = self._accounts_urlchannels_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("accounts", Some(opt)) => { + match opt.subcommand() { + ("adclients-list", Some(opt)) => { + call_result = self._accounts_adclients_list(opt, dry_run, &mut err); + }, + ("adunits-customchannels-list", Some(opt)) => { + call_result = self._accounts_adunits_customchannels_list(opt, dry_run, &mut err); + }, + ("adunits-get", Some(opt)) => { + call_result = self._accounts_adunits_get(opt, dry_run, &mut err); + }, + ("adunits-get-ad-code", Some(opt)) => { + call_result = self._accounts_adunits_get_ad_code(opt, dry_run, &mut err); + }, + ("adunits-list", Some(opt)) => { + call_result = self._accounts_adunits_list(opt, dry_run, &mut err); + }, + ("alerts-delete", Some(opt)) => { + call_result = self._accounts_alerts_delete(opt, dry_run, &mut err); + }, + ("alerts-list", Some(opt)) => { + call_result = self._accounts_alerts_list(opt, dry_run, &mut err); + }, + ("customchannels-adunits-list", Some(opt)) => { + call_result = self._accounts_customchannels_adunits_list(opt, dry_run, &mut err); + }, + ("customchannels-get", Some(opt)) => { + call_result = self._accounts_customchannels_get(opt, dry_run, &mut err); + }, + ("customchannels-list", Some(opt)) => { + call_result = self._accounts_customchannels_list(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._accounts_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._accounts_list(opt, dry_run, &mut err); + }, + ("payments-list", Some(opt)) => { + call_result = self._accounts_payments_list(opt, dry_run, &mut err); + }, + ("reports-generate", Some(opt)) => { + call_result = self._accounts_reports_generate(opt, dry_run, &mut err); + }, + ("reports-saved-generate", Some(opt)) => { + call_result = self._accounts_reports_saved_generate(opt, dry_run, &mut err); + }, + ("reports-saved-list", Some(opt)) => { + call_result = self._accounts_reports_saved_list(opt, dry_run, &mut err); + }, + ("savedadstyles-get", Some(opt)) => { + call_result = self._accounts_savedadstyles_get(opt, dry_run, &mut err); + }, + ("savedadstyles-list", Some(opt)) => { + call_result = self._accounts_savedadstyles_list(opt, dry_run, &mut err); + }, + ("urlchannels-list", Some(opt)) => { + call_result = self._accounts_urlchannels_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("accounts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("adclients", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._adclients_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("adclients".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("adunits", Some(opt)) => { + match opt.subcommand() { + ("customchannels-list", Some(opt)) => { + call_result = self._adunits_customchannels_list(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._adunits_get(opt, dry_run, &mut err); + }, + ("get-ad-code", Some(opt)) => { + call_result = self._adunits_get_ad_code(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._adunits_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("adunits".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("alerts", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._alerts_delete(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._alerts_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("alerts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("customchannels", Some(opt)) => { + match opt.subcommand() { + ("adunits-list", Some(opt)) => { + call_result = self._customchannels_adunits_list(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._customchannels_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._customchannels_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("customchannels".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("metadata", Some(opt)) => { + match opt.subcommand() { + ("dimensions-list", Some(opt)) => { + call_result = self._metadata_dimensions_list(opt, dry_run, &mut err); + }, + ("metrics-list", Some(opt)) => { + call_result = self._metadata_metrics_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("metadata".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("payments", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._payments_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("payments".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("reports", Some(opt)) => { + match opt.subcommand() { + ("generate", Some(opt)) => { + call_result = self._reports_generate(opt, dry_run, &mut err); + }, + ("saved-generate", Some(opt)) => { + call_result = self._reports_saved_generate(opt, dry_run, &mut err); + }, + ("saved-list", Some(opt)) => { + call_result = self._reports_saved_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("reports".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("savedadstyles", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._savedadstyles_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._savedadstyles_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("savedadstyles".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("urlchannels", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._urlchannels_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("urlchannels".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_adclients { - if self.opt.cmd_list { - call_result = self._adclients_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_adunits { - if self.opt.cmd_customchannels_list { - call_result = self._adunits_customchannels_list(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._adunits_get(dry_run, &mut err); - } else if self.opt.cmd_get_ad_code { - call_result = self._adunits_get_ad_code(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._adunits_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_alerts { - if self.opt.cmd_delete { - call_result = self._alerts_delete(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._alerts_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_customchannels { - if self.opt.cmd_adunits_list { - call_result = self._customchannels_adunits_list(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._customchannels_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._customchannels_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_metadata { - if self.opt.cmd_dimensions_list { - call_result = self._metadata_dimensions_list(dry_run, &mut err); - } else if self.opt.cmd_metrics_list { - call_result = self._metadata_metrics_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_payments { - if self.opt.cmd_list { - call_result = self._payments_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_reports { - if self.opt.cmd_generate { - call_result = self._reports_generate(dry_run, &mut err); - } else if self.opt.cmd_saved_generate { - call_result = self._reports_saved_generate(dry_run, &mut err); - } else if self.opt.cmd_saved_list { - call_result = self._reports_saved_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_savedadstyles { - if self.opt.cmd_get { - call_result = self._savedadstyles_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._savedadstyles_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_urlchannels { - if self.opt.cmd_list { - call_result = self._urlchannels_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -2212,7 +2376,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2225,7 +2389,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2235,37 +2399,1073 @@ impl Engine { let engine = Engine { opt: opt, hub: api::AdSense::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("accounts", "methods: 'adclients-list', 'adunits-customchannels-list', 'adunits-get', 'adunits-get-ad-code', 'adunits-list', 'alerts-delete', 'alerts-list', 'customchannels-adunits-list', 'customchannels-get', 'customchannels-list', 'get', 'list', 'payments-list', 'reports-generate', 'reports-saved-generate', 'reports-saved-list', 'savedadstyles-get', 'savedadstyles-list' and 'urlchannels-list'", vec![ + ("adclients-list", + Some(r##"List all ad clients in the specified account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_adclients-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account for which to list ad clients."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("adunits-customchannels-list", + Some(r##"List all custom channels which the specified ad unit belongs to."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_adunits-customchannels-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to which the ad client belongs."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client which contains the ad unit."##), + Some(true), + Some(false)), + + (Some(r##"ad-unit-id"##), + None, + Some(r##"Ad unit for which to list custom channels."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("adunits-get", + Some(r##"Gets the specified ad unit in the specified ad client for the specified account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_adunits-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to which the ad client belongs."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to get the ad unit."##), + Some(true), + Some(false)), + + (Some(r##"ad-unit-id"##), + None, + Some(r##"Ad unit to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("adunits-get-ad-code", + Some(r##"Get ad code for the specified ad unit."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_adunits-get-ad-code", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account which contains the ad client."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client with contains the ad unit."##), + Some(true), + Some(false)), + + (Some(r##"ad-unit-id"##), + None, + Some(r##"Ad unit to get the code for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("adunits-list", + Some(r##"List all ad units in the specified ad client for the specified account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_adunits-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to which the ad client belongs."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to list ad units."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("alerts-delete", + Some(r##"Dismiss (delete) the specified alert from the specified publisher AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_alerts-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account which contains the ad unit."##), + Some(true), + Some(false)), + + (Some(r##"alert-id"##), + None, + Some(r##"Alert to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("alerts-list", + Some(r##"List the alerts for the specified AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_alerts-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account for which to retrieve the alerts."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("customchannels-adunits-list", + Some(r##"List all ad units in the specified custom channel."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_customchannels-adunits-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to which the ad client belongs."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client which contains the custom channel."##), + Some(true), + Some(false)), + + (Some(r##"custom-channel-id"##), + None, + Some(r##"Custom channel for which to list ad units."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("customchannels-get", + Some(r##"Get the specified custom channel from the specified ad client for the specified account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_customchannels-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to which the ad client belongs."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client which contains the custom channel."##), + Some(true), + Some(false)), + + (Some(r##"custom-channel-id"##), + None, + Some(r##"Custom channel to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("customchannels-list", + Some(r##"List all custom channels in the specified ad client for the specified account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_customchannels-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to which the ad client belongs."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to list custom channels."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Get information about the selected AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to get information about."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all accounts available to this AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("payments-list", + Some(r##"List the payments for the specified AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_payments-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account for which to retrieve the payments."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reports-generate", + Some(r##"Generate an AdSense report based on the report request sent in the query parameters. Returns the result as JSON; to retrieve output in CSV format specify "alt=csv" as a query parameter."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_reports-generate", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account upon which to report."##), + Some(true), + Some(false)), + + (Some(r##"start-date"##), + None, + Some(r##"Start of the date range to report on in "YYYY-MM-DD" format, inclusive."##), + Some(true), + Some(false)), + + (Some(r##"end-date"##), + None, + Some(r##"End of the date range to report on in "YYYY-MM-DD" format, inclusive."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reports-saved-generate", + Some(r##"Generate an AdSense report based on the saved report ID sent in the query parameters."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_reports-saved-generate", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to which the saved reports belong."##), + Some(true), + Some(false)), + + (Some(r##"saved-report-id"##), + None, + Some(r##"The saved report to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reports-saved-list", + Some(r##"List all saved reports in the specified AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_reports-saved-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to which the saved reports belong."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("savedadstyles-get", + Some(r##"List a specific saved ad style for the specified account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_savedadstyles-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account for which to get the saved ad style."##), + Some(true), + Some(false)), + + (Some(r##"saved-ad-style-id"##), + None, + Some(r##"Saved ad style to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("savedadstyles-list", + Some(r##"List all saved ad styles in the specified account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_savedadstyles-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account for which to list saved ad styles."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("urlchannels-list", + Some(r##"List all URL channels in the specified ad client for the specified account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/accounts_urlchannels-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to which the ad client belongs."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to list URL channels."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("adclients", "methods: 'list'", vec![ + ("list", + Some(r##"List all ad clients in this AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/adclients_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("adunits", "methods: 'customchannels-list', 'get', 'get-ad-code' and 'list'", vec![ + ("customchannels-list", + Some(r##"List all custom channels which the specified ad unit belongs to."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/adunits_customchannels-list", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client which contains the ad unit."##), + Some(true), + Some(false)), + + (Some(r##"ad-unit-id"##), + None, + Some(r##"Ad unit for which to list custom channels."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Gets the specified ad unit in the specified ad client."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/adunits_get", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to get the ad unit."##), + Some(true), + Some(false)), + + (Some(r##"ad-unit-id"##), + None, + Some(r##"Ad unit to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-ad-code", + Some(r##"Get ad code for the specified ad unit."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/adunits_get-ad-code", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client with contains the ad unit."##), + Some(true), + Some(false)), + + (Some(r##"ad-unit-id"##), + None, + Some(r##"Ad unit to get the code for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all ad units in the specified ad client for this AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/adunits_list", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to list ad units."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("alerts", "methods: 'delete' and 'list'", vec![ + ("delete", + Some(r##"Dismiss (delete) the specified alert from the publisher's AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/alerts_delete", + vec![ + (Some(r##"alert-id"##), + None, + Some(r##"Alert to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("list", + Some(r##"List the alerts for this AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/alerts_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("customchannels", "methods: 'adunits-list', 'get' and 'list'", vec![ + ("adunits-list", + Some(r##"List all ad units in the specified custom channel."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/customchannels_adunits-list", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client which contains the custom channel."##), + Some(true), + Some(false)), + + (Some(r##"custom-channel-id"##), + None, + Some(r##"Custom channel for which to list ad units."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Get the specified custom channel from the specified ad client."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/customchannels_get", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client which contains the custom channel."##), + Some(true), + Some(false)), + + (Some(r##"custom-channel-id"##), + None, + Some(r##"Custom channel to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all custom channels in the specified ad client for this AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/customchannels_list", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to list custom channels."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("metadata", "methods: 'dimensions-list' and 'metrics-list'", vec![ + ("dimensions-list", + Some(r##"List the metadata for the dimensions available to this AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/metadata_dimensions-list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("metrics-list", + Some(r##"List the metadata for the metrics available to this AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/metadata_metrics-list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("payments", "methods: 'list'", vec![ + ("list", + Some(r##"List the payments for this AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/payments_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("reports", "methods: 'generate', 'saved-generate' and 'saved-list'", vec![ + ("generate", + Some(r##"Generate an AdSense report based on the report request sent in the query parameters. Returns the result as JSON; to retrieve output in CSV format specify "alt=csv" as a query parameter."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/reports_generate", + vec![ + (Some(r##"start-date"##), + None, + Some(r##"Start of the date range to report on in "YYYY-MM-DD" format, inclusive."##), + Some(true), + Some(false)), + + (Some(r##"end-date"##), + None, + Some(r##"End of the date range to report on in "YYYY-MM-DD" format, inclusive."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("saved-generate", + Some(r##"Generate an AdSense report based on the saved report ID sent in the query parameters."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/reports_saved-generate", + vec![ + (Some(r##"saved-report-id"##), + None, + Some(r##"The saved report to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("saved-list", + Some(r##"List all saved reports in this AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/reports_saved-list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("savedadstyles", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Get a specific saved ad style from the user's account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/savedadstyles_get", + vec![ + (Some(r##"saved-ad-style-id"##), + None, + Some(r##"Saved ad style to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all saved ad styles in the user's account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/savedadstyles_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("urlchannels", "methods: 'list'", vec![ + ("list", + Some(r##"List all URL channels in the specified ad client for this AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsense1d4_cli/urlchannels_list", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to list URL channels."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("adsense1d4") + .author("Sebastian Thiel ") + .version("0.2.0+20150326") + .about("Gives AdSense publishers access to their inventory and the ability to generate reports") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_adsense1d4_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/adsense1d4/Cargo.toml b/gen/adsense1d4/Cargo.toml index a0772201e8..cb08188db8 100644 --- a/gen/adsense1d4/Cargo.toml +++ b/gen/adsense1d4/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-adsense1d4" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel "] description = "A complete library to interact with AdSense (protocol v1.4)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/adsense1d4" @@ -15,9 +15,10 @@ keywords = ["adsense", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/adsense1d4/README.md b/gen/adsense1d4/README.md index d66bb2f058..4cc1f2be24 100644 --- a/gen/adsense1d4/README.md +++ b/gen/adsense1d4/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-adsense1d4` library allows access to all features of the *Google AdSense* service. -This documentation was generated from *AdSense* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *adsense:v1.4* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *AdSense* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *adsense:v1.4* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *AdSense* *v1d4* API can be found at the [official documentation site](https://developers.google.com/adsense/management/). @@ -207,7 +207,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_adsense1d4/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_adsense1d4/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/adsense1d4/src/cmn.rs b/gen/adsense1d4/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/adsense1d4/src/cmn.rs +++ b/gen/adsense1d4/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/adsense1d4/src/lib.rs b/gen/adsense1d4/src/lib.rs index 0144ca66d2..de7a21eb78 100644 --- a/gen/adsense1d4/src/lib.rs +++ b/gen/adsense1d4/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *AdSense* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *adsense:v1.4* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *AdSense* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *adsense:v1.4* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *AdSense* *v1d4* API can be found at the //! [official documentation site](https://developers.google.com/adsense/management/). @@ -208,7 +208,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -217,7 +217,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -233,6 +232,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -362,7 +362,7 @@ impl<'a, C, A> AdSense AdSense { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -398,7 +398,7 @@ impl<'a, C, A> AdSense } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -2462,7 +2462,7 @@ impl<'a, C, A> UrlchannelListCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2484,7 +2484,7 @@ impl<'a, C, A> UrlchannelListCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2727,7 +2727,7 @@ impl<'a, C, A> AdunitCustomchannelListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2749,7 +2749,7 @@ impl<'a, C, A> AdunitCustomchannelListCall<'a, C, A> where C: BorrowMut AdunitGetCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3014,7 +3014,7 @@ impl<'a, C, A> AdunitGetCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3256,7 +3256,7 @@ impl<'a, C, A> AdunitListCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3278,7 +3278,7 @@ impl<'a, C, A> AdunitListCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3518,7 +3518,7 @@ impl<'a, C, A> AdunitGetAdCodeCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3540,7 +3540,7 @@ impl<'a, C, A> AdunitGetAdCodeCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3751,7 +3751,7 @@ impl<'a, C, A> AdclientListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3773,7 +3773,7 @@ impl<'a, C, A> AdclientListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3993,7 +3993,7 @@ impl<'a, C, A> AlertDeleteCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4015,7 +4015,7 @@ impl<'a, C, A> AlertDeleteCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4201,7 +4201,7 @@ impl<'a, C, A> AlertListCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4223,7 +4223,7 @@ impl<'a, C, A> AlertListCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4421,7 +4421,7 @@ impl<'a, C, A> SavedadstyleListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4443,7 +4443,7 @@ impl<'a, C, A> SavedadstyleListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4664,7 +4664,7 @@ impl<'a, C, A> SavedadstyleGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4686,7 +4686,7 @@ impl<'a, C, A> SavedadstyleGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4887,7 +4887,7 @@ impl<'a, C, A> ReportSavedListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4909,7 +4909,7 @@ impl<'a, C, A> ReportSavedListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5199,7 +5199,7 @@ impl<'a, C, A> ReportGenerateCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5221,7 +5221,7 @@ impl<'a, C, A> ReportGenerateCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5538,7 +5538,7 @@ impl<'a, C, A> ReportSavedGenerateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5560,7 +5560,7 @@ impl<'a, C, A> ReportSavedGenerateCall<'a, C, A> where C: BorrowMut AccountAlertDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5821,7 +5821,7 @@ impl<'a, C, A> AccountAlertDeleteCall<'a, C, A> where C: BorrowMut AccountAlertListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6065,7 +6065,7 @@ impl<'a, C, A> AccountAlertListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6306,7 +6306,7 @@ impl<'a, C, A> AccountReportSavedGenerateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6328,7 +6328,7 @@ impl<'a, C, A> AccountReportSavedGenerateCall<'a, C, A> where C: BorrowMut AccountListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6582,7 +6582,7 @@ impl<'a, C, A> AccountListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6803,7 +6803,7 @@ impl<'a, C, A> AccountPaymentListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6825,7 +6825,7 @@ impl<'a, C, A> AccountPaymentListCall<'a, C, A> where C: BorrowMut AccountSavedadstyleGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7066,7 +7066,7 @@ impl<'a, C, A> AccountSavedadstyleGetCall<'a, C, A> where C: BorrowMut AccountAdunitGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7319,7 +7319,7 @@ impl<'a, C, A> AccountAdunitGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7560,7 +7560,7 @@ impl<'a, C, A> AccountCustomchannelGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7582,7 +7582,7 @@ impl<'a, C, A> AccountCustomchannelGetCall<'a, C, A> where C: BorrowMut AccountCustomchannelAdunitListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7860,7 +7860,7 @@ impl<'a, C, A> AccountCustomchannelAdunitListCall<'a, C, A> where C: BorrowMut AccountReportSavedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8150,7 +8150,7 @@ impl<'a, C, A> AccountReportSavedListCall<'a, C, A> where C: BorrowMut AccountUrlchannelListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8415,7 +8415,7 @@ impl<'a, C, A> AccountUrlchannelListCall<'a, C, A> where C: BorrowMut AccountAdunitListCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8695,7 +8695,7 @@ impl<'a, C, A> AccountAdunitListCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9029,7 +9029,7 @@ impl<'a, C, A> AccountReportGenerateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9051,7 +9051,7 @@ impl<'a, C, A> AccountReportGenerateCall<'a, C, A> where C: BorrowMut AccountAdclientListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9387,7 +9387,7 @@ impl<'a, C, A> AccountAdclientListCall<'a, C, A> where C: BorrowMut AccountCustomchannelListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9652,7 +9652,7 @@ impl<'a, C, A> AccountCustomchannelListCall<'a, C, A> where C: BorrowMut AccountSavedadstyleListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9925,7 +9925,7 @@ impl<'a, C, A> AccountSavedadstyleListCall<'a, C, A> where C: BorrowMut AccountAdunitGetAdCodeCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10182,7 +10182,7 @@ impl<'a, C, A> AccountAdunitGetAdCodeCall<'a, C, A> where C: BorrowMut AccountAdunitCustomchannelListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10455,7 +10455,7 @@ impl<'a, C, A> AccountAdunitCustomchannelListCall<'a, C, A> where C: BorrowMut AccountGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10733,7 +10733,7 @@ impl<'a, C, A> AccountGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10931,7 +10931,7 @@ impl<'a, C, A> PaymentListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10953,7 +10953,7 @@ impl<'a, C, A> PaymentListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11134,7 +11134,7 @@ impl<'a, C, A> MetadataDimensionListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11156,7 +11156,7 @@ impl<'a, C, A> MetadataDimensionListCall<'a, C, A> where C: BorrowMut MetadataMetricListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11359,7 +11359,7 @@ impl<'a, C, A> MetadataMetricListCall<'a, C, A> where C: BorrowMut CustomchannelGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11590,7 +11590,7 @@ impl<'a, C, A> CustomchannelGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11827,7 +11827,7 @@ impl<'a, C, A> CustomchannelListCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11849,7 +11849,7 @@ impl<'a, C, A> CustomchannelListCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12097,7 +12097,7 @@ impl<'a, C, A> CustomchannelAdunitListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12119,7 +12119,7 @@ impl<'a, C, A> CustomchannelAdunitListCall<'a, C, A> where C: BorrowMut"] description = "A complete library to interact with AdSense Host (protocol v4.1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/adsensehost4d1-cli" @@ -17,15 +17,14 @@ keywords = ["adsensehost", "google", "cli"] name = "adsensehost4d1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-adsensehost4d1] path = "../adsensehost4d1" diff --git a/gen/adsensehost4d1-cli/README.md b/gen/adsensehost4d1-cli/README.md index a6488ce9f5..06dec50c7e 100644 --- a/gen/adsensehost4d1-cli/README.md +++ b/gen/adsensehost4d1-cli/README.md @@ -10,46 +10,53 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *AdSense Host* API can be found at the +[official documentation site](https://developers.google.com/adsense/host/). + # Usage -This documentation was generated from the *AdSense Host* API at revision *20150307*. The CLI is at version *0.1.0*. +This documentation was generated from the *AdSense Host* API at revision *20150307*. The CLI is at version *0.2.0*. ```bash - adsensehost4d1 [options] accounts adclients-get [-p ...] [-o ] - adsensehost4d1 [options] accounts adclients-list [-p ...] [-o ] - adsensehost4d1 [options] accounts adunits-delete [-p ...] [-o ] - adsensehost4d1 [options] accounts adunits-get [-p ...] [-o ] - adsensehost4d1 [options] accounts adunits-get-ad-code [-p ...] [-o ] - adsensehost4d1 [options] accounts adunits-insert -r ... [-p ...] [-o ] - adsensehost4d1 [options] accounts adunits-list [-p ...] [-o ] - adsensehost4d1 [options] accounts adunits-patch -r ... [-p ...] [-o ] - adsensehost4d1 [options] accounts adunits-update -r ... [-p ...] [-o ] - adsensehost4d1 [options] accounts get [-p ...] [-o ] - adsensehost4d1 [options] accounts list ... [-p ...] [-o ] - adsensehost4d1 [options] accounts reports-generate [-p ...] [-o ] - adsensehost4d1 [options] adclients get [-p ...] [-o ] - adsensehost4d1 [options] adclients list [-p ...] [-o ] - adsensehost4d1 [options] associationsessions start ... [-p ...] [-o ] - adsensehost4d1 [options] associationsessions verify [-p ...] [-o ] - adsensehost4d1 [options] customchannels delete [-p ...] [-o ] - adsensehost4d1 [options] customchannels get [-p ...] [-o ] - adsensehost4d1 [options] customchannels insert -r ... [-p ...] [-o ] - adsensehost4d1 [options] customchannels list [-p ...] [-o ] - adsensehost4d1 [options] customchannels patch -r ... [-p ...] [-o ] - adsensehost4d1 [options] customchannels update -r ... [-p ...] [-o ] - adsensehost4d1 [options] reports generate [-p ...] [-o ] - adsensehost4d1 [options] urlchannels delete [-p ...] [-o ] - adsensehost4d1 [options] urlchannels insert -r ... [-p ...] [-o ] - adsensehost4d1 [options] urlchannels list [-p ...] [-o ] +adsensehost4d1 [options] + accounts + adclients-get [-p ]... [-o ] + adclients-list [-p ]... [-o ] + adunits-delete [-p ]... [-o ] + adunits-get [-p ]... [-o ] + adunits-get-ad-code [-p ]... [-o ] + adunits-insert (-r )... [-p ]... [-o ] + adunits-list [-p ]... [-o ] + adunits-patch (-r )... [-p ]... [-o ] + adunits-update (-r )... [-p ]... [-o ] + get [-p ]... [-o ] + list ... [-p ]... [-o ] + reports-generate [-p ]... [-o ] + adclients + get [-p ]... [-o ] + list [-p ]... [-o ] + associationsessions + start ... [-p ]... [-o ] + verify [-p ]... [-o ] + customchannels + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + reports + generate [-p ]... [-o ] + urlchannels + delete [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] adsensehost4d1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/adsensehost4d1-cli/mkdocs.yml b/gen/adsensehost4d1-cli/mkdocs.yml index ce5a1ae27c..5c492f3e40 100644 --- a/gen/adsensehost4d1-cli/mkdocs.yml +++ b/gen/adsensehost4d1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: AdSense Host v0.1.0+20150307 +site_name: AdSense Host v0.2.0+20150307 site_url: http://byron.github.io/google-apis-rs/google-adsensehost4d1-cli site_description: Write integrating applications with bcore diff --git a/gen/adsensehost4d1-cli/src/cmn.rs b/gen/adsensehost4d1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/adsensehost4d1-cli/src/cmn.rs +++ b/gen/adsensehost4d1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/adsensehost4d1-cli/src/main.rs b/gen/adsensehost4d1-cli/src/main.rs index 575e9c2697..c54395b169 100644 --- a/gen/adsensehost4d1-cli/src/main.rs +++ b/gen/adsensehost4d1-cli/src/main.rs @@ -2,138 +2,103 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_adsensehost4d1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - adsensehost4d1 [options] accounts adclients-get [-p ...] [-o ] - adsensehost4d1 [options] accounts adclients-list [-p ...] [-o ] - adsensehost4d1 [options] accounts adunits-delete [-p ...] [-o ] - adsensehost4d1 [options] accounts adunits-get [-p ...] [-o ] - adsensehost4d1 [options] accounts adunits-get-ad-code [-p ...] [-o ] - adsensehost4d1 [options] accounts adunits-insert -r ... [-p ...] [-o ] - adsensehost4d1 [options] accounts adunits-list [-p ...] [-o ] - adsensehost4d1 [options] accounts adunits-patch -r ... [-p ...] [-o ] - adsensehost4d1 [options] accounts adunits-update -r ... [-p ...] [-o ] - adsensehost4d1 [options] accounts get [-p ...] [-o ] - adsensehost4d1 [options] accounts list ... [-p ...] [-o ] - adsensehost4d1 [options] accounts reports-generate [-p ...] [-o ] - adsensehost4d1 [options] adclients get [-p ...] [-o ] - adsensehost4d1 [options] adclients list [-p ...] [-o ] - adsensehost4d1 [options] associationsessions start ... [-p ...] [-o ] - adsensehost4d1 [options] associationsessions verify [-p ...] [-o ] - adsensehost4d1 [options] customchannels delete [-p ...] [-o ] - adsensehost4d1 [options] customchannels get [-p ...] [-o ] - adsensehost4d1 [options] customchannels insert -r ... [-p ...] [-o ] - adsensehost4d1 [options] customchannels list [-p ...] [-o ] - adsensehost4d1 [options] customchannels patch -r ... [-p ...] [-o ] - adsensehost4d1 [options] customchannels update -r ... [-p ...] [-o ] - adsensehost4d1 [options] reports generate [-p ...] [-o ] - adsensehost4d1 [options] urlchannels delete [-p ...] [-o ] - adsensehost4d1 [options] urlchannels insert -r ... [-p ...] [-o ] - adsensehost4d1 [options] urlchannels list [-p ...] [-o ] - adsensehost4d1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::AdSenseHost>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _accounts_adclients_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().adclients_get(&self.opt.arg_account_id, &self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _accounts_adclients_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().adclients_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_adclients_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().adclients_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_adclients_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().adclients_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -142,193 +107,209 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_adunits_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().adunits_delete(&self.opt.arg_account_id, &self.opt.arg_ad_client_id, &self.opt.arg_ad_unit_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_adunits_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().adunits_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("ad-unit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_adunits_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().adunits_get(&self.opt.arg_account_id, &self.opt.arg_ad_client_id, &self.opt.arg_ad_unit_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_adunits_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().adunits_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("ad-unit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_adunits_get_ad_code(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().adunits_get_ad_code(&self.opt.arg_account_id, &self.opt.arg_ad_client_id, &self.opt.arg_ad_unit_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_adunits_get_ad_code(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().adunits_get_ad_code(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("ad-unit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "host-custom-channel-id" => { call = call.add_host_custom_channel_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["host-custom-channel-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_adunits_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounts_adunits_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AdUnit::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -471,58 +452,63 @@ impl Engine { request.custom_style.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["background", "backup-option", "border", "code", "color", "colors", "content-ads-settings", "corners", "custom-style", "family", "font", "id", "kind", "markup-language", "mobile-content-ads-settings", "name", "scripting-language", "size", "status", "text", "title", "type", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().adunits_insert(request, &self.opt.arg_account_id, &self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().adunits_insert(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_adunits_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().adunits_list(&self.opt.arg_account_id, &self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_adunits_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().adunits_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -534,52 +520,56 @@ impl Engine { "include-inactive" => { call = call.include_inactive(arg_from_str(value.unwrap_or("false"), err, "include-inactive", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["include-inactive", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_adunits_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounts_adunits_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AdUnit::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -722,60 +712,65 @@ impl Engine { request.custom_style.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["background", "backup-option", "border", "code", "color", "colors", "content-ads-settings", "corners", "custom-style", "family", "font", "id", "kind", "markup-language", "mobile-content-ads-settings", "name", "scripting-language", "size", "status", "text", "title", "type", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().adunits_patch(request, &self.opt.arg_account_id, &self.opt.arg_ad_client_id, &self.opt.arg_ad_unit_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().adunits_patch(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("ad-unit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_adunits_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounts_adunits_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AdUnit::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -918,150 +913,163 @@ impl Engine { request.custom_style.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["background", "backup-option", "border", "code", "color", "colors", "content-ads-settings", "corners", "custom-style", "family", "font", "id", "kind", "markup-language", "mobile-content-ads-settings", "name", "scripting-language", "size", "status", "text", "title", "type", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().adunits_update(request, &self.opt.arg_account_id, &self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().adunits_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().get(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().get(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().list(&self.opt.arg_filter_ad_client_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().list(&opt.values_of("filter-ad-client-id").unwrap_or(Vec::new()).iter().map(|&v| v.to_string()).collect::>()); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_reports_generate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().reports_generate(&self.opt.arg_account_id, &self.opt.arg_start_date, &self.opt.arg_end_date); - for parg in self.opt.arg_v.iter() { + fn _accounts_reports_generate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().reports_generate(opt.value_of("account-id").unwrap_or(""), opt.value_of("start-date").unwrap_or(""), opt.value_of("end-date").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -1085,96 +1093,104 @@ impl Engine { "dimension" => { call = call.add_dimension(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sort", "locale", "metric", "max-results", "filter", "start-index", "dimension"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _adclients_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.adclients().get(&self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + fn _adclients_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.adclients().get(opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _adclients_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _adclients_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.adclients().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1183,50 +1199,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _associationsessions_start(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.associationsessions().start(&self.opt.arg_product_code, &self.opt.arg_website_url); - for parg in self.opt.arg_v.iter() { + fn _associationsessions_start(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.associationsessions().start(&opt.values_of("product-code").unwrap_or(Vec::new()).iter().map(|&v| v.to_string()).collect::>(), opt.value_of("website-url").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "website-locale" => { @@ -1235,190 +1255,206 @@ impl Engine { "user-locale" => { call = call.user_locale(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["website-locale", "user-locale"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _associationsessions_verify(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.associationsessions().verify(&self.opt.arg_token); - for parg in self.opt.arg_v.iter() { + fn _associationsessions_verify(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.associationsessions().verify(opt.value_of("token").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _customchannels_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.customchannels().delete(&self.opt.arg_ad_client_id, &self.opt.arg_custom_channel_id); - for parg in self.opt.arg_v.iter() { + fn _customchannels_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.customchannels().delete(opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("custom-channel-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _customchannels_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.customchannels().get(&self.opt.arg_ad_client_id, &self.opt.arg_custom_channel_id); - for parg in self.opt.arg_v.iter() { + fn _customchannels_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.customchannels().get(opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("custom-channel-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _customchannels_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _customchannels_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CustomChannel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1446,58 +1482,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["code", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.customchannels().insert(request, &self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.customchannels().insert(request, opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _customchannels_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.customchannels().list(&self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + fn _customchannels_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.customchannels().list(opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1506,52 +1547,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _customchannels_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _customchannels_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CustomChannel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1579,60 +1624,65 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["code", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.customchannels().patch(request, &self.opt.arg_ad_client_id, &self.opt.arg_custom_channel_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.customchannels().patch(request, opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("custom-channel-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _customchannels_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _customchannels_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CustomChannel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1660,58 +1710,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["code", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.customchannels().update(request, &self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.customchannels().update(request, opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _reports_generate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.reports().generate(&self.opt.arg_start_date, &self.opt.arg_end_date); - for parg in self.opt.arg_v.iter() { + fn _reports_generate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.reports().generate(opt.value_of("start-date").unwrap_or(""), opt.value_of("end-date").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -1735,98 +1790,106 @@ impl Engine { "dimension" => { call = call.add_dimension(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sort", "locale", "metric", "max-results", "filter", "start-index", "dimension"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _urlchannels_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.urlchannels().delete(&self.opt.arg_ad_client_id, &self.opt.arg_url_channel_id); - for parg in self.opt.arg_v.iter() { + fn _urlchannels_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.urlchannels().delete(opt.value_of("ad-client-id").unwrap_or(""), opt.value_of("url-channel-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _urlchannels_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _urlchannels_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UrlChannel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1851,58 +1914,63 @@ impl Engine { request.url_pattern = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "kind", "url-pattern"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.urlchannels().insert(request, &self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.urlchannels().insert(request, opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _urlchannels_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.urlchannels().list(&self.opt.arg_ad_client_id); - for parg in self.opt.arg_v.iter() { + fn _urlchannels_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.urlchannels().list(opt.value_of("ad-client-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1911,148 +1979,201 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_accounts { - if self.opt.cmd_adclients_get { - call_result = self._accounts_adclients_get(dry_run, &mut err); - } else if self.opt.cmd_adclients_list { - call_result = self._accounts_adclients_list(dry_run, &mut err); - } else if self.opt.cmd_adunits_delete { - call_result = self._accounts_adunits_delete(dry_run, &mut err); - } else if self.opt.cmd_adunits_get { - call_result = self._accounts_adunits_get(dry_run, &mut err); - } else if self.opt.cmd_adunits_get_ad_code { - call_result = self._accounts_adunits_get_ad_code(dry_run, &mut err); - } else if self.opt.cmd_adunits_insert { - call_result = self._accounts_adunits_insert(dry_run, &mut err); - } else if self.opt.cmd_adunits_list { - call_result = self._accounts_adunits_list(dry_run, &mut err); - } else if self.opt.cmd_adunits_patch { - call_result = self._accounts_adunits_patch(dry_run, &mut err); - } else if self.opt.cmd_adunits_update { - call_result = self._accounts_adunits_update(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._accounts_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._accounts_list(dry_run, &mut err); - } else if self.opt.cmd_reports_generate { - call_result = self._accounts_reports_generate(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("accounts", Some(opt)) => { + match opt.subcommand() { + ("adclients-get", Some(opt)) => { + call_result = self._accounts_adclients_get(opt, dry_run, &mut err); + }, + ("adclients-list", Some(opt)) => { + call_result = self._accounts_adclients_list(opt, dry_run, &mut err); + }, + ("adunits-delete", Some(opt)) => { + call_result = self._accounts_adunits_delete(opt, dry_run, &mut err); + }, + ("adunits-get", Some(opt)) => { + call_result = self._accounts_adunits_get(opt, dry_run, &mut err); + }, + ("adunits-get-ad-code", Some(opt)) => { + call_result = self._accounts_adunits_get_ad_code(opt, dry_run, &mut err); + }, + ("adunits-insert", Some(opt)) => { + call_result = self._accounts_adunits_insert(opt, dry_run, &mut err); + }, + ("adunits-list", Some(opt)) => { + call_result = self._accounts_adunits_list(opt, dry_run, &mut err); + }, + ("adunits-patch", Some(opt)) => { + call_result = self._accounts_adunits_patch(opt, dry_run, &mut err); + }, + ("adunits-update", Some(opt)) => { + call_result = self._accounts_adunits_update(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._accounts_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._accounts_list(opt, dry_run, &mut err); + }, + ("reports-generate", Some(opt)) => { + call_result = self._accounts_reports_generate(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("accounts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("adclients", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._adclients_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._adclients_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("adclients".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("associationsessions", Some(opt)) => { + match opt.subcommand() { + ("start", Some(opt)) => { + call_result = self._associationsessions_start(opt, dry_run, &mut err); + }, + ("verify", Some(opt)) => { + call_result = self._associationsessions_verify(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("associationsessions".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("customchannels", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._customchannels_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._customchannels_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._customchannels_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._customchannels_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._customchannels_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._customchannels_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("customchannels".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("reports", Some(opt)) => { + match opt.subcommand() { + ("generate", Some(opt)) => { + call_result = self._reports_generate(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("reports".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("urlchannels", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._urlchannels_delete(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._urlchannels_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._urlchannels_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("urlchannels".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_adclients { - if self.opt.cmd_get { - call_result = self._adclients_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._adclients_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_associationsessions { - if self.opt.cmd_start { - call_result = self._associationsessions_start(dry_run, &mut err); - } else if self.opt.cmd_verify { - call_result = self._associationsessions_verify(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_customchannels { - if self.opt.cmd_delete { - call_result = self._customchannels_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._customchannels_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._customchannels_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._customchannels_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._customchannels_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._customchannels_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_reports { - if self.opt.cmd_generate { - call_result = self._reports_generate(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_urlchannels { - if self.opt.cmd_delete { - call_result = self._urlchannels_delete(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._urlchannels_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._urlchannels_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -2065,7 +2186,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2078,7 +2199,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2088,37 +2209,869 @@ impl Engine { let engine = Engine { opt: opt, hub: api::AdSenseHost::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("accounts", "methods: 'adclients-get', 'adclients-list', 'adunits-delete', 'adunits-get', 'adunits-get-ad-code', 'adunits-insert', 'adunits-list', 'adunits-patch', 'adunits-update', 'get', 'list' and 'reports-generate'", vec![ + ("adclients-get", + Some(r##"Get information about one of the ad clients in the specified publisher's AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/accounts_adclients-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account which contains the ad client."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("adclients-list", + Some(r##"List all hosted ad clients in the specified hosted account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/accounts_adclients-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account for which to list ad clients."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("adunits-delete", + Some(r##"Delete the specified ad unit from the specified publisher AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/accounts_adunits-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account which contains the ad unit."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to get ad unit."##), + Some(true), + Some(false)), + + (Some(r##"ad-unit-id"##), + None, + Some(r##"Ad unit to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("adunits-get", + Some(r##"Get the specified host ad unit in this AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/accounts_adunits-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account which contains the ad unit."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to get ad unit."##), + Some(true), + Some(false)), + + (Some(r##"ad-unit-id"##), + None, + Some(r##"Ad unit to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("adunits-get-ad-code", + Some(r##"Get ad code for the specified ad unit, attaching the specified host custom channels."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/accounts_adunits-get-ad-code", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account which contains the ad client."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client with contains the ad unit."##), + Some(true), + Some(false)), + + (Some(r##"ad-unit-id"##), + None, + Some(r##"Ad unit to get the code for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("adunits-insert", + Some(r##"Insert the supplied ad unit into the specified publisher AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/accounts_adunits-insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account which will contain the ad unit."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client into which to insert the ad unit."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("adunits-list", + Some(r##"List all ad units in the specified publisher's AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/accounts_adunits-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account which contains the ad client."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to list ad units."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("adunits-patch", + Some(r##"Update the supplied ad unit in the specified publisher AdSense account. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/accounts_adunits-patch", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account which contains the ad client."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client which contains the ad unit."##), + Some(true), + Some(false)), + + (Some(r##"ad-unit-id"##), + None, + Some(r##"Ad unit to get."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("adunits-update", + Some(r##"Update the supplied ad unit in the specified publisher AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/accounts_adunits-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account which contains the ad client."##), + Some(true), + Some(false)), + + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client which contains the ad unit."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Get information about the selected associated AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/accounts_get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account to get information about."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List hosted accounts associated with this AdSense account by ad client id."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/accounts_list", + vec![ + (Some(r##"filter-ad-client-id"##), + None, + Some(r##"Ad clients to list accounts for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reports-generate", + Some(r##"Generate an AdSense report based on the report request sent in the query parameters. Returns the result as JSON; to retrieve output in CSV format specify "alt=csv" as a query parameter."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/accounts_reports-generate", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Hosted account upon which to report."##), + Some(true), + Some(false)), + + (Some(r##"start-date"##), + None, + Some(r##"Start of the date range to report on in "YYYY-MM-DD" format, inclusive."##), + Some(true), + Some(false)), + + (Some(r##"end-date"##), + None, + Some(r##"End of the date range to report on in "YYYY-MM-DD" format, inclusive."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("adclients", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Get information about one of the ad clients in the Host AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/adclients_get", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all host ad clients in this AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/adclients_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("associationsessions", "methods: 'start' and 'verify'", vec![ + ("start", + Some(r##"Create an association session for initiating an association with an AdSense user."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/associationsessions_start", + vec![ + (Some(r##"product-code"##), + None, + Some(r##"Products to associate with the user."##), + Some(true), + Some(false)), + + (Some(r##"website-url"##), + None, + Some(r##"The URL of the user's hosted website."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("verify", + Some(r##"Verify an association session after the association callback returns from AdSense signup."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/associationsessions_verify", + vec![ + (Some(r##"token"##), + None, + Some(r##"The token returned to the association callback URL."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("customchannels", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Delete a specific custom channel from the host AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/customchannels_delete", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client from which to delete the custom channel."##), + Some(true), + Some(false)), + + (Some(r##"custom-channel-id"##), + None, + Some(r##"Custom channel to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Get a specific custom channel from the host AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/customchannels_get", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client from which to get the custom channel."##), + Some(true), + Some(false)), + + (Some(r##"custom-channel-id"##), + None, + Some(r##"Custom channel to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Add a new custom channel to the host AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/customchannels_insert", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client to which the new custom channel will be added."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all host custom channels in this AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/customchannels_list", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to list custom channels."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update a custom channel in the host AdSense account. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/customchannels_patch", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client in which the custom channel will be updated."##), + Some(true), + Some(false)), + + (Some(r##"custom-channel-id"##), + None, + Some(r##"Custom channel to get."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update a custom channel in the host AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/customchannels_update", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client in which the custom channel will be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("reports", "methods: 'generate'", vec![ + ("generate", + Some(r##"Generate an AdSense report based on the report request sent in the query parameters. Returns the result as JSON; to retrieve output in CSV format specify "alt=csv" as a query parameter."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/reports_generate", + vec![ + (Some(r##"start-date"##), + None, + Some(r##"Start of the date range to report on in "YYYY-MM-DD" format, inclusive."##), + Some(true), + Some(false)), + + (Some(r##"end-date"##), + None, + Some(r##"End of the date range to report on in "YYYY-MM-DD" format, inclusive."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("urlchannels", "methods: 'delete', 'insert' and 'list'", vec![ + ("delete", + Some(r##"Delete a URL channel from the host AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/urlchannels_delete", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client from which to delete the URL channel."##), + Some(true), + Some(false)), + + (Some(r##"url-channel-id"##), + None, + Some(r##"URL channel to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Add a new URL channel to the host AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/urlchannels_insert", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client to which the new URL channel will be added."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all host URL channels in the host AdSense account."##), + "Details at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli/urlchannels_list", + vec![ + (Some(r##"ad-client-id"##), + None, + Some(r##"Ad client for which to list URL channels."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("adsensehost4d1") + .author("Sebastian Thiel ") + .version("0.2.0+20150307") + .about("Gives AdSense Hosts access to report generation, ad code generation, and publisher management capabilities.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_adsensehost4d1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/adsensehost4d1/Cargo.toml b/gen/adsensehost4d1/Cargo.toml index 7256b4aab0..fa67d2947d 100644 --- a/gen/adsensehost4d1/Cargo.toml +++ b/gen/adsensehost4d1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-adsensehost4d1" -version = "0.1.6+20150307" +version = "0.1.7+20150307" authors = ["Sebastian Thiel "] description = "A complete library to interact with AdSense Host (protocol v4.1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/adsensehost4d1" @@ -15,9 +15,10 @@ keywords = ["adsensehost", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/adsensehost4d1/README.md b/gen/adsensehost4d1/README.md index 598a745ace..ddecd647ff 100644 --- a/gen/adsensehost4d1/README.md +++ b/gen/adsensehost4d1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-adsensehost4d1` library allows access to all features of the *Google AdSense Host* service. -This documentation was generated from *AdSense Host* crate version *0.1.6+20150307*, where *20150307* is the exact revision of the *adsensehost:v4.1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *AdSense Host* crate version *0.1.7+20150307*, where *20150307* is the exact revision of the *adsensehost:v4.1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *AdSense Host* *v4d1* API can be found at the [official documentation site](https://developers.google.com/adsense/host/). @@ -185,7 +185,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_adsensehost4d1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_adsensehost4d1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/adsensehost4d1/src/cmn.rs b/gen/adsensehost4d1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/adsensehost4d1/src/cmn.rs +++ b/gen/adsensehost4d1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/adsensehost4d1/src/lib.rs b/gen/adsensehost4d1/src/lib.rs index d54e075600..c5a7fb65f0 100644 --- a/gen/adsensehost4d1/src/lib.rs +++ b/gen/adsensehost4d1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *AdSense Host* crate version *0.1.6+20150307*, where *20150307* is the exact revision of the *adsensehost:v4.1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *AdSense Host* crate version *0.1.7+20150307*, where *20150307* is the exact revision of the *adsensehost:v4.1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *AdSense Host* *v4d1* API can be found at the //! [official documentation site](https://developers.google.com/adsense/host/). @@ -186,7 +186,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -195,7 +195,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -211,6 +210,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -334,7 +334,7 @@ impl<'a, C, A> AdSenseHost AdSenseHost { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -358,7 +358,7 @@ impl<'a, C, A> AdSenseHost } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1727,6 +1727,7 @@ impl<'a, C, A> UrlchannelInsertCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, UrlChannel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1782,11 +1783,20 @@ impl<'a, C, A> UrlchannelInsertCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1809,7 +1819,7 @@ impl<'a, C, A> UrlchannelInsertCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2040,7 +2050,7 @@ impl<'a, C, A> UrlchannelDeleteCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2062,7 +2072,7 @@ impl<'a, C, A> UrlchannelDeleteCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2299,7 +2309,7 @@ impl<'a, C, A> UrlchannelListCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2321,7 +2331,7 @@ impl<'a, C, A> UrlchannelListCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2536,7 +2546,7 @@ impl<'a, C, A> AdclientListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2558,7 +2568,7 @@ impl<'a, C, A> AdclientListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2779,7 +2789,7 @@ impl<'a, C, A> AdclientGetCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2801,7 +2811,7 @@ impl<'a, C, A> AdclientGetCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3012,7 +3022,7 @@ impl<'a, C, A> AssociationsessionStartCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3034,7 +3044,7 @@ impl<'a, C, A> AssociationsessionStartCall<'a, C, A> where C: BorrowMut AssociationsessionVerifyCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3274,7 +3284,7 @@ impl<'a, C, A> AssociationsessionVerifyCall<'a, C, A> where C: BorrowMut ReportGenerateCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3542,7 +3552,7 @@ impl<'a, C, A> ReportGenerateCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3839,7 +3849,7 @@ impl<'a, C, A> AccountAdunitListCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3861,7 +3871,7 @@ impl<'a, C, A> AccountAdunitListCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4091,7 +4101,7 @@ impl<'a, C, A> AccountListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4113,7 +4123,7 @@ impl<'a, C, A> AccountListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4344,7 +4354,7 @@ impl<'a, C, A> AccountAdunitGetAdCodeCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4366,7 +4376,7 @@ impl<'a, C, A> AccountAdunitGetAdCodeCall<'a, C, A> where C: BorrowMut AccountReportGenerateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4688,7 +4698,7 @@ impl<'a, C, A> AccountReportGenerateCall<'a, C, A> where C: BorrowMut AccountAdunitDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5004,7 +5014,7 @@ impl<'a, C, A> AccountAdunitDeleteCall<'a, C, A> where C: BorrowMut AccountAdclientListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5273,7 +5283,7 @@ impl<'a, C, A> AccountAdclientListCall<'a, C, A> where C: BorrowMut AccountAdunitPatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, AdUnit)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5515,11 +5526,20 @@ impl<'a, C, A> AccountAdunitPatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5542,7 +5562,7 @@ impl<'a, C, A> AccountAdunitPatchCall<'a, C, A> where C: BorrowMut AccountAdclientGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5815,7 +5835,7 @@ impl<'a, C, A> AccountAdclientGetCall<'a, C, A> where C: BorrowMut AccountGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6064,7 +6084,7 @@ impl<'a, C, A> AccountGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6234,6 +6254,7 @@ impl<'a, C, A> AccountAdunitInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, AdUnit)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6290,11 +6311,20 @@ impl<'a, C, A> AccountAdunitInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6317,7 +6347,7 @@ impl<'a, C, A> AccountAdunitInsertCall<'a, C, A> where C: BorrowMut AccountAdunitGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6582,7 +6612,7 @@ impl<'a, C, A> AccountAdunitGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6772,6 +6802,7 @@ impl<'a, C, A> AccountAdunitUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, AdUnit)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6828,11 +6859,20 @@ impl<'a, C, A> AccountAdunitUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6855,7 +6895,7 @@ impl<'a, C, A> AccountAdunitUpdateCall<'a, C, A> where C: BorrowMut CustomchannelGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7118,7 +7158,7 @@ impl<'a, C, A> CustomchannelGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7347,7 +7387,7 @@ impl<'a, C, A> CustomchannelDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7369,7 +7409,7 @@ impl<'a, C, A> CustomchannelDeleteCall<'a, C, A> where C: BorrowMut CustomchannelUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, CustomChannel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7603,11 +7644,20 @@ impl<'a, C, A> CustomchannelUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7630,7 +7680,7 @@ impl<'a, C, A> CustomchannelUpdateCall<'a, C, A> where C: BorrowMut CustomchannelListCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7891,7 +7941,7 @@ impl<'a, C, A> CustomchannelListCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8075,6 +8125,7 @@ impl<'a, C, A> CustomchannelPatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, CustomChannel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8131,11 +8182,20 @@ impl<'a, C, A> CustomchannelPatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8158,7 +8218,7 @@ impl<'a, C, A> CustomchannelPatchCall<'a, C, A> where C: BorrowMut CustomchannelInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, CustomChannel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8404,11 +8465,20 @@ impl<'a, C, A> CustomchannelInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8431,7 +8501,7 @@ impl<'a, C, A> CustomchannelInsertCall<'a, C, A> where C: BorrowMut"] description = "A complete library to interact with analytics (protocol v3)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/analytics3-cli" @@ -17,15 +17,14 @@ keywords = ["analytics", "google", "cli"] name = "analytics3" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-analytics3] path = "../analytics3" diff --git a/gen/analytics3-cli/README.md b/gen/analytics3-cli/README.md index f439aede30..80dfcc37fe 100644 --- a/gen/analytics3-cli/README.md +++ b/gen/analytics3-cli/README.md @@ -10,98 +10,103 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *analytics* API can be found at the +[official documentation site](https://developers.google.com/analytics/). + # Usage -This documentation was generated from the *analytics* API at revision *20150305*. The CLI is at version *0.1.0*. +This documentation was generated from the *analytics* API at revision *20150305*. The CLI is at version *0.2.0*. ```bash - analytics3 [options] data ga-get [-p ...] [-o ] - analytics3 [options] data mcf-get [-p ...] [-o ] - analytics3 [options] data realtime-get [-p ...] [-o ] - analytics3 [options] management account-summaries-list [-p ...] [-o ] - analytics3 [options] management account-user-links-delete [-p ...] - analytics3 [options] management account-user-links-insert -r ... [-p ...] [-o ] - analytics3 [options] management account-user-links-list [-p ...] [-o ] - analytics3 [options] management account-user-links-update -r ... [-p ...] [-o ] - analytics3 [options] management accounts-list [-p ...] [-o ] - analytics3 [options] management custom-data-sources-list [-p ...] [-o ] - analytics3 [options] management custom-dimensions-get [-p ...] [-o ] - analytics3 [options] management custom-dimensions-insert -r ... [-p ...] [-o ] - analytics3 [options] management custom-dimensions-list [-p ...] [-o ] - analytics3 [options] management custom-dimensions-patch -r ... [-p ...] [-o ] - analytics3 [options] management custom-dimensions-update -r ... [-p ...] [-o ] - analytics3 [options] management custom-metrics-get [-p ...] [-o ] - analytics3 [options] management custom-metrics-insert -r ... [-p ...] [-o ] - analytics3 [options] management custom-metrics-list [-p ...] [-o ] - analytics3 [options] management custom-metrics-patch -r ... [-p ...] [-o ] - analytics3 [options] management custom-metrics-update -r ... [-p ...] [-o ] - analytics3 [options] management experiments-delete [-p ...] - analytics3 [options] management experiments-get [-p ...] [-o ] - analytics3 [options] management experiments-insert -r ... [-p ...] [-o ] - analytics3 [options] management experiments-list [-p ...] [-o ] - analytics3 [options] management experiments-patch -r ... [-p ...] [-o ] - analytics3 [options] management experiments-update -r ... [-p ...] [-o ] - analytics3 [options] management filters-delete [-p ...] [-o ] - analytics3 [options] management filters-get [-p ...] [-o ] - analytics3 [options] management filters-insert -r ... [-p ...] [-o ] - analytics3 [options] management filters-list [-p ...] [-o ] - analytics3 [options] management filters-patch -r ... [-p ...] [-o ] - analytics3 [options] management filters-update -r ... [-p ...] [-o ] - analytics3 [options] management goals-get [-p ...] [-o ] - analytics3 [options] management goals-insert -r ... [-p ...] [-o ] - analytics3 [options] management goals-list [-p ...] [-o ] - analytics3 [options] management goals-patch -r ... [-p ...] [-o ] - analytics3 [options] management goals-update -r ... [-p ...] [-o ] - analytics3 [options] management profile-filter-links-delete [-p ...] - analytics3 [options] management profile-filter-links-get [-p ...] [-o ] - analytics3 [options] management profile-filter-links-insert -r ... [-p ...] [-o ] - analytics3 [options] management profile-filter-links-list [-p ...] [-o ] - analytics3 [options] management profile-filter-links-patch -r ... [-p ...] [-o ] - analytics3 [options] management profile-filter-links-update -r ... [-p ...] [-o ] - analytics3 [options] management profile-user-links-delete [-p ...] - analytics3 [options] management profile-user-links-insert -r ... [-p ...] [-o ] - analytics3 [options] management profile-user-links-list [-p ...] [-o ] - analytics3 [options] management profile-user-links-update -r ... [-p ...] [-o ] - analytics3 [options] management profiles-delete [-p ...] - analytics3 [options] management profiles-get [-p ...] [-o ] - analytics3 [options] management profiles-insert -r ... [-p ...] [-o ] - analytics3 [options] management profiles-list [-p ...] [-o ] - analytics3 [options] management profiles-patch -r ... [-p ...] [-o ] - analytics3 [options] management profiles-update -r ... [-p ...] [-o ] - analytics3 [options] management segments-list [-p ...] [-o ] - analytics3 [options] management unsampled-reports-get [-p ...] [-o ] - analytics3 [options] management unsampled-reports-insert -r ... [-p ...] [-o ] - analytics3 [options] management unsampled-reports-list [-p ...] [-o ] - analytics3 [options] management uploads-delete-upload-data -r ... [-p ...] - analytics3 [options] management uploads-get [-p ...] [-o ] - analytics3 [options] management uploads-list [-p ...] [-o ] - analytics3 [options] management uploads-upload-data -u (simple|resumable) [-p ...] [-o ] - analytics3 [options] management web-property-ad-words-links-delete [-p ...] - analytics3 [options] management web-property-ad-words-links-get [-p ...] [-o ] - analytics3 [options] management web-property-ad-words-links-insert -r ... [-p ...] [-o ] - analytics3 [options] management web-property-ad-words-links-list [-p ...] [-o ] - analytics3 [options] management web-property-ad-words-links-patch -r ... [-p ...] [-o ] - analytics3 [options] management web-property-ad-words-links-update -r ... [-p ...] [-o ] - analytics3 [options] management webproperties-get [-p ...] [-o ] - analytics3 [options] management webproperties-insert -r ... [-p ...] [-o ] - analytics3 [options] management webproperties-list [-p ...] [-o ] - analytics3 [options] management webproperties-patch -r ... [-p ...] [-o ] - analytics3 [options] management webproperties-update -r ... [-p ...] [-o ] - analytics3 [options] management webproperty-user-links-delete [-p ...] - analytics3 [options] management webproperty-user-links-insert -r ... [-p ...] [-o ] - analytics3 [options] management webproperty-user-links-list [-p ...] [-o ] - analytics3 [options] management webproperty-user-links-update -r ... [-p ...] [-o ] - analytics3 [options] metadata columns-list [-p ...] [-o ] - analytics3 [options] provisioning create-account-ticket -r ... [-p ...] [-o ] +analytics3 [options] + data + ga-get [-p ]... [-o ] + mcf-get [-p ]... [-o ] + realtime-get [-p ]... [-o ] + management + account-summaries-list [-p ]... [-o ] + account-user-links-delete [-p ]... + account-user-links-insert (-r )... [-p ]... [-o ] + account-user-links-list [-p ]... [-o ] + account-user-links-update (-r )... [-p ]... [-o ] + accounts-list [-p ]... [-o ] + custom-data-sources-list [-p ]... [-o ] + custom-dimensions-get [-p ]... [-o ] + custom-dimensions-insert (-r )... [-p ]... [-o ] + custom-dimensions-list [-p ]... [-o ] + custom-dimensions-patch (-r )... [-p ]... [-o ] + custom-dimensions-update (-r )... [-p ]... [-o ] + custom-metrics-get [-p ]... [-o ] + custom-metrics-insert (-r )... [-p ]... [-o ] + custom-metrics-list [-p ]... [-o ] + custom-metrics-patch (-r )... [-p ]... [-o ] + custom-metrics-update (-r )... [-p ]... [-o ] + experiments-delete [-p ]... + experiments-get [-p ]... [-o ] + experiments-insert (-r )... [-p ]... [-o ] + experiments-list [-p ]... [-o ] + experiments-patch (-r )... [-p ]... [-o ] + experiments-update (-r )... [-p ]... [-o ] + filters-delete [-p ]... [-o ] + filters-get [-p ]... [-o ] + filters-insert (-r )... [-p ]... [-o ] + filters-list [-p ]... [-o ] + filters-patch (-r )... [-p ]... [-o ] + filters-update (-r )... [-p ]... [-o ] + goals-get [-p ]... [-o ] + goals-insert (-r )... [-p ]... [-o ] + goals-list [-p ]... [-o ] + goals-patch (-r )... [-p ]... [-o ] + goals-update (-r )... [-p ]... [-o ] + profile-filter-links-delete [-p ]... + profile-filter-links-get [-p ]... [-o ] + profile-filter-links-insert (-r )... [-p ]... [-o ] + profile-filter-links-list [-p ]... [-o ] + profile-filter-links-patch (-r )... [-p ]... [-o ] + profile-filter-links-update (-r )... [-p ]... [-o ] + profile-user-links-delete [-p ]... + profile-user-links-insert (-r )... [-p ]... [-o ] + profile-user-links-list [-p ]... [-o ] + profile-user-links-update (-r )... [-p ]... [-o ] + profiles-delete [-p ]... + profiles-get [-p ]... [-o ] + profiles-insert (-r )... [-p ]... [-o ] + profiles-list [-p ]... [-o ] + profiles-patch (-r )... [-p ]... [-o ] + profiles-update (-r )... [-p ]... [-o ] + segments-list [-p ]... [-o ] + unsampled-reports-get [-p ]... [-o ] + unsampled-reports-insert (-r )... [-p ]... [-o ] + unsampled-reports-list [-p ]... [-o ] + uploads-delete-upload-data (-r )... [-p ]... + uploads-get [-p ]... [-o ] + uploads-list [-p ]... [-o ] + uploads-upload-data (-u (simple|resumable) -f [-m ]) [-p ]... [-o ] + web-property-ad-words-links-delete [-p ]... + web-property-ad-words-links-get [-p ]... [-o ] + web-property-ad-words-links-insert (-r )... [-p ]... [-o ] + web-property-ad-words-links-list [-p ]... [-o ] + web-property-ad-words-links-patch (-r )... [-p ]... [-o ] + web-property-ad-words-links-update (-r )... [-p ]... [-o ] + webproperties-get [-p ]... [-o ] + webproperties-insert (-r )... [-p ]... [-o ] + webproperties-list [-p ]... [-o ] + webproperties-patch (-r )... [-p ]... [-o ] + webproperties-update (-r )... [-p ]... [-o ] + webproperty-user-links-delete [-p ]... + webproperty-user-links-insert (-r )... [-p ]... [-o ] + webproperty-user-links-list [-p ]... [-o ] + webproperty-user-links-update (-r )... [-p ]... [-o ] + metadata + columns-list [-p ]... [-o ] + provisioning + create-account-ticket (-r )... [-p ]... [-o ] analytics3 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_analytics3_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/analytics3-cli/mkdocs.yml b/gen/analytics3-cli/mkdocs.yml index 49d293021f..06b538e0e8 100644 --- a/gen/analytics3-cli/mkdocs.yml +++ b/gen/analytics3-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: analytics v0.1.0+20150305 +site_name: analytics v0.2.0+20150305 site_url: http://byron.github.io/google-apis-rs/google-analytics3-cli site_description: Write integrating applications with bcore diff --git a/gen/analytics3-cli/src/cmn.rs b/gen/analytics3-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/analytics3-cli/src/cmn.rs +++ b/gen/analytics3-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/analytics3-cli/src/main.rs b/gen/analytics3-cli/src/main.rs index 34c265db23..fc8a60481a 100644 --- a/gen/analytics3-cli/src/main.rs +++ b/gen/analytics3-cli/src/main.rs @@ -2,144 +2,53 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_analytics3 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - analytics3 [options] data ga-get [-p ...] [-o ] - analytics3 [options] data mcf-get [-p ...] [-o ] - analytics3 [options] data realtime-get [-p ...] [-o ] - analytics3 [options] management account-summaries-list [-p ...] [-o ] - analytics3 [options] management account-user-links-delete [-p ...] - analytics3 [options] management account-user-links-insert -r ... [-p ...] [-o ] - analytics3 [options] management account-user-links-list [-p ...] [-o ] - analytics3 [options] management account-user-links-update -r ... [-p ...] [-o ] - analytics3 [options] management accounts-list [-p ...] [-o ] - analytics3 [options] management custom-data-sources-list [-p ...] [-o ] - analytics3 [options] management custom-dimensions-get [-p ...] [-o ] - analytics3 [options] management custom-dimensions-insert -r ... [-p ...] [-o ] - analytics3 [options] management custom-dimensions-list [-p ...] [-o ] - analytics3 [options] management custom-dimensions-patch -r ... [-p ...] [-o ] - analytics3 [options] management custom-dimensions-update -r ... [-p ...] [-o ] - analytics3 [options] management custom-metrics-get [-p ...] [-o ] - analytics3 [options] management custom-metrics-insert -r ... [-p ...] [-o ] - analytics3 [options] management custom-metrics-list [-p ...] [-o ] - analytics3 [options] management custom-metrics-patch -r ... [-p ...] [-o ] - analytics3 [options] management custom-metrics-update -r ... [-p ...] [-o ] - analytics3 [options] management experiments-delete [-p ...] - analytics3 [options] management experiments-get [-p ...] [-o ] - analytics3 [options] management experiments-insert -r ... [-p ...] [-o ] - analytics3 [options] management experiments-list [-p ...] [-o ] - analytics3 [options] management experiments-patch -r ... [-p ...] [-o ] - analytics3 [options] management experiments-update -r ... [-p ...] [-o ] - analytics3 [options] management filters-delete [-p ...] [-o ] - analytics3 [options] management filters-get [-p ...] [-o ] - analytics3 [options] management filters-insert -r ... [-p ...] [-o ] - analytics3 [options] management filters-list [-p ...] [-o ] - analytics3 [options] management filters-patch -r ... [-p ...] [-o ] - analytics3 [options] management filters-update -r ... [-p ...] [-o ] - analytics3 [options] management goals-get [-p ...] [-o ] - analytics3 [options] management goals-insert -r ... [-p ...] [-o ] - analytics3 [options] management goals-list [-p ...] [-o ] - analytics3 [options] management goals-patch -r ... [-p ...] [-o ] - analytics3 [options] management goals-update -r ... [-p ...] [-o ] - analytics3 [options] management profile-filter-links-delete [-p ...] - analytics3 [options] management profile-filter-links-get [-p ...] [-o ] - analytics3 [options] management profile-filter-links-insert -r ... [-p ...] [-o ] - analytics3 [options] management profile-filter-links-list [-p ...] [-o ] - analytics3 [options] management profile-filter-links-patch -r ... [-p ...] [-o ] - analytics3 [options] management profile-filter-links-update -r ... [-p ...] [-o ] - analytics3 [options] management profile-user-links-delete [-p ...] - analytics3 [options] management profile-user-links-insert -r ... [-p ...] [-o ] - analytics3 [options] management profile-user-links-list [-p ...] [-o ] - analytics3 [options] management profile-user-links-update -r ... [-p ...] [-o ] - analytics3 [options] management profiles-delete [-p ...] - analytics3 [options] management profiles-get [-p ...] [-o ] - analytics3 [options] management profiles-insert -r ... [-p ...] [-o ] - analytics3 [options] management profiles-list [-p ...] [-o ] - analytics3 [options] management profiles-patch -r ... [-p ...] [-o ] - analytics3 [options] management profiles-update -r ... [-p ...] [-o ] - analytics3 [options] management segments-list [-p ...] [-o ] - analytics3 [options] management unsampled-reports-get [-p ...] [-o ] - analytics3 [options] management unsampled-reports-insert -r ... [-p ...] [-o ] - analytics3 [options] management unsampled-reports-list [-p ...] [-o ] - analytics3 [options] management uploads-delete-upload-data -r ... [-p ...] - analytics3 [options] management uploads-get [-p ...] [-o ] - analytics3 [options] management uploads-list [-p ...] [-o ] - analytics3 [options] management uploads-upload-data -u (simple|resumable) [-p ...] [-o ] - analytics3 [options] management web-property-ad-words-links-delete [-p ...] - analytics3 [options] management web-property-ad-words-links-get [-p ...] [-o ] - analytics3 [options] management web-property-ad-words-links-insert -r ... [-p ...] [-o ] - analytics3 [options] management web-property-ad-words-links-list [-p ...] [-o ] - analytics3 [options] management web-property-ad-words-links-patch -r ... [-p ...] [-o ] - analytics3 [options] management web-property-ad-words-links-update -r ... [-p ...] [-o ] - analytics3 [options] management webproperties-get [-p ...] [-o ] - analytics3 [options] management webproperties-insert -r ... [-p ...] [-o ] - analytics3 [options] management webproperties-list [-p ...] [-o ] - analytics3 [options] management webproperties-patch -r ... [-p ...] [-o ] - analytics3 [options] management webproperties-update -r ... [-p ...] [-o ] - analytics3 [options] management webproperty-user-links-delete [-p ...] - analytics3 [options] management webproperty-user-links-insert -r ... [-p ...] [-o ] - analytics3 [options] management webproperty-user-links-list [-p ...] [-o ] - analytics3 [options] management webproperty-user-links-update -r ... [-p ...] [-o ] - analytics3 [options] metadata columns-list [-p ...] [-o ] - analytics3 [options] provisioning create-account-ticket -r ... [-p ...] [-o ] - analytics3 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_analytics3_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Analytics>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _data_ga_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.data().ga_get(&self.opt.arg_ids, &self.opt.arg_start_date, &self.opt.arg_end_date, &self.opt.arg_metrics); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _data_ga_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.data().ga_get(opt.value_of("ids").unwrap_or(""), opt.value_of("start-date").unwrap_or(""), opt.value_of("end-date").unwrap_or(""), opt.value_of("metrics").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -166,50 +75,54 @@ impl Engine { "dimensions" => { call = call.dimensions(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sort", "max-results", "dimensions", "start-index", "sampling-level", "filters", "output", "segment"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _data_mcf_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.data().mcf_get(&self.opt.arg_ids, &self.opt.arg_start_date, &self.opt.arg_end_date, &self.opt.arg_metrics); - for parg in self.opt.arg_v.iter() { + fn _data_mcf_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.data().mcf_get(opt.value_of("ids").unwrap_or(""), opt.value_of("start-date").unwrap_or(""), opt.value_of("end-date").unwrap_or(""), opt.value_of("metrics").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -230,50 +143,54 @@ impl Engine { "dimensions" => { call = call.dimensions(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sort", "max-results", "dimensions", "start-index", "sampling-level", "filters"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _data_realtime_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.data().realtime_get(&self.opt.arg_ids, &self.opt.arg_metrics); - for parg in self.opt.arg_v.iter() { + fn _data_realtime_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.data().realtime_get(opt.value_of("ids").unwrap_or(""), opt.value_of("metrics").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "sort" => { @@ -288,50 +205,54 @@ impl Engine { "dimensions" => { call = call.dimensions(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sort", "max-results", "dimensions", "filters"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_account_summaries_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_account_summaries_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.management().account_summaries_list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -340,96 +261,99 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_account_user_links_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().account_user_links_delete(&self.opt.arg_account_id, &self.opt.arg_link_id); - for parg in self.opt.arg_v.iter() { + fn _management_account_user_links_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().account_user_links_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _management_account_user_links_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_account_user_links_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::EntityUserLink::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -589,58 +513,63 @@ impl Engine { request.permissions.as_mut().unwrap().effective.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "account-ref", "effective", "email", "entity", "href", "id", "internal-web-property-id", "kind", "local", "name", "permissions", "profile-ref", "self-link", "user-ref", "web-property-id", "web-property-ref"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().account_user_links_insert(request, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().account_user_links_insert(request, opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_account_user_links_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().account_user_links_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _management_account_user_links_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().account_user_links_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -649,52 +578,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_account_user_links_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_account_user_links_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::EntityUserLink::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -854,58 +787,63 @@ impl Engine { request.permissions.as_mut().unwrap().effective.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "account-ref", "effective", "email", "entity", "href", "id", "internal-web-property-id", "kind", "local", "name", "permissions", "profile-ref", "self-link", "user-ref", "web-property-id", "web-property-ref"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().account_user_links_update(request, &self.opt.arg_account_id, &self.opt.arg_link_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().account_user_links_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_accounts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_accounts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.management().accounts_list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -914,50 +852,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_custom_data_sources_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().custom_data_sources_list(&self.opt.arg_account_id, &self.opt.arg_web_property_id); - for parg in self.opt.arg_v.iter() { + fn _management_custom_data_sources_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().custom_data_sources_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -966,98 +908,106 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_custom_dimensions_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().custom_dimensions_get(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_custom_dimension_id); - for parg in self.opt.arg_v.iter() { + fn _management_custom_dimensions_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().custom_dimensions_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("custom-dimension-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_custom_dimensions_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_custom_dimensions_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CustomDimension::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1123,58 +1073,63 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "created", "href", "id", "index", "kind", "name", "parent-link", "scope", "self-link", "type", "updated", "web-property-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().custom_dimensions_insert(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().custom_dimensions_insert(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_custom_dimensions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().custom_dimensions_list(&self.opt.arg_account_id, &self.opt.arg_web_property_id); - for parg in self.opt.arg_v.iter() { + fn _management_custom_dimensions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().custom_dimensions_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -1183,52 +1138,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_custom_dimensions_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_custom_dimensions_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CustomDimension::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1294,63 +1253,68 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "created", "href", "id", "index", "kind", "name", "parent-link", "scope", "self-link", "type", "updated", "web-property-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().custom_dimensions_patch(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_custom_dimension_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().custom_dimensions_patch(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("custom-dimension-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "ignore-custom-data-source-links" => { call = call.ignore_custom_data_source_links(arg_from_str(value.unwrap_or("false"), err, "ignore-custom-data-source-links", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["ignore-custom-data-source-links"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_custom_dimensions_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_custom_dimensions_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CustomDimension::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1416,109 +1380,118 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "created", "href", "id", "index", "kind", "name", "parent-link", "scope", "self-link", "type", "updated", "web-property-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().custom_dimensions_update(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_custom_dimension_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().custom_dimensions_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("custom-dimension-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "ignore-custom-data-source-links" => { call = call.ignore_custom_data_source_links(arg_from_str(value.unwrap_or("false"), err, "ignore-custom-data-source-links", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["ignore-custom-data-source-links"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_custom_metrics_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().custom_metrics_get(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_custom_metric_id); - for parg in self.opt.arg_v.iter() { + fn _management_custom_metrics_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().custom_metrics_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("custom-metric-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_custom_metrics_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_custom_metrics_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CustomMetric::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1594,58 +1567,63 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "created", "href", "id", "index", "kind", "max-value", "min-value", "name", "parent-link", "scope", "self-link", "type", "updated", "web-property-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().custom_metrics_insert(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().custom_metrics_insert(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_custom_metrics_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().custom_metrics_list(&self.opt.arg_account_id, &self.opt.arg_web_property_id); - for parg in self.opt.arg_v.iter() { + fn _management_custom_metrics_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().custom_metrics_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -1654,52 +1632,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_custom_metrics_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_custom_metrics_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CustomMetric::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1775,63 +1757,68 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "created", "href", "id", "index", "kind", "max-value", "min-value", "name", "parent-link", "scope", "self-link", "type", "updated", "web-property-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().custom_metrics_patch(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_custom_metric_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().custom_metrics_patch(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("custom-metric-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "ignore-custom-data-source-links" => { call = call.ignore_custom_data_source_links(arg_from_str(value.unwrap_or("false"), err, "ignore-custom-data-source-links", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["ignore-custom-data-source-links"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_custom_metrics_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_custom_metrics_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CustomMetric::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1907,153 +1894,161 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "created", "href", "id", "index", "kind", "max-value", "min-value", "name", "parent-link", "scope", "self-link", "type", "updated", "web-property-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().custom_metrics_update(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_custom_metric_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().custom_metrics_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("custom-metric-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "ignore-custom-data-source-links" => { call = call.ignore_custom_data_source_links(arg_from_str(value.unwrap_or("false"), err, "ignore-custom-data-source-links", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["ignore-custom-data-source-links"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_experiments_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().experiments_delete(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id, &self.opt.arg_experiment_id); - for parg in self.opt.arg_v.iter() { + fn _management_experiments_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().experiments_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or(""), opt.value_of("experiment-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _management_experiments_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().experiments_get(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id, &self.opt.arg_experiment_id); - for parg in self.opt.arg_v.iter() { + fn _management_experiments_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().experiments_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or(""), opt.value_of("experiment-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_experiments_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_experiments_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Experiment::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2163,58 +2158,63 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "created", "description", "editable-in-ga-ui", "end-time", "equal-weighting", "href", "id", "internal-web-property-id", "kind", "minimum-experiment-length-in-days", "name", "objective-metric", "optimization-type", "parent-link", "profile-id", "reason-experiment-ended", "rewrite-variation-urls-as-original", "self-link", "serving-framework", "snippet", "start-time", "status", "traffic-coverage", "type", "updated", "web-property-id", "winner-confidence-level", "winner-found"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().experiments_insert(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().experiments_insert(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_experiments_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().experiments_list(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id); - for parg in self.opt.arg_v.iter() { + fn _management_experiments_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().experiments_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -2223,52 +2223,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_experiments_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_experiments_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Experiment::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2378,60 +2382,65 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "created", "description", "editable-in-ga-ui", "end-time", "equal-weighting", "href", "id", "internal-web-property-id", "kind", "minimum-experiment-length-in-days", "name", "objective-metric", "optimization-type", "parent-link", "profile-id", "reason-experiment-ended", "rewrite-variation-urls-as-original", "self-link", "serving-framework", "snippet", "start-time", "status", "traffic-coverage", "type", "updated", "web-property-id", "winner-confidence-level", "winner-found"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().experiments_patch(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id, &self.opt.arg_experiment_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().experiments_patch(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or(""), opt.value_of("experiment-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_experiments_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_experiments_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Experiment::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2541,152 +2550,165 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "created", "description", "editable-in-ga-ui", "end-time", "equal-weighting", "href", "id", "internal-web-property-id", "kind", "minimum-experiment-length-in-days", "name", "objective-metric", "optimization-type", "parent-link", "profile-id", "reason-experiment-ended", "rewrite-variation-urls-as-original", "self-link", "serving-framework", "snippet", "start-time", "status", "traffic-coverage", "type", "updated", "web-property-id", "winner-confidence-level", "winner-found"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().experiments_update(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id, &self.opt.arg_experiment_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().experiments_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or(""), opt.value_of("experiment-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_filters_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().filters_delete(&self.opt.arg_account_id, &self.opt.arg_filter_id); - for parg in self.opt.arg_v.iter() { + fn _management_filters_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().filters_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("filter-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_filters_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().filters_get(&self.opt.arg_account_id, &self.opt.arg_filter_id); - for parg in self.opt.arg_v.iter() { + fn _management_filters_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().filters_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("filter-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_filters_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_filters_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Filter::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2885,58 +2907,63 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advanced-details", "case-sensitive", "created", "exclude-details", "expression-value", "extract-a", "extract-b", "field", "field-a", "field-a-required", "field-b", "field-b-required", "href", "id", "include-details", "kind", "lowercase-details", "match-type", "name", "output-constructor", "output-to-field", "override-output-field", "parent-link", "replace-string", "search-and-replace-details", "search-string", "self-link", "type", "updated", "uppercase-details"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().filters_insert(request, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().filters_insert(request, opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_filters_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().filters_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _management_filters_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().filters_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -2945,52 +2972,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_filters_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_filters_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Filter::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3189,60 +3220,65 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advanced-details", "case-sensitive", "created", "exclude-details", "expression-value", "extract-a", "extract-b", "field", "field-a", "field-a-required", "field-b", "field-b-required", "href", "id", "include-details", "kind", "lowercase-details", "match-type", "name", "output-constructor", "output-to-field", "override-output-field", "parent-link", "replace-string", "search-and-replace-details", "search-string", "self-link", "type", "updated", "uppercase-details"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().filters_patch(request, &self.opt.arg_account_id, &self.opt.arg_filter_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().filters_patch(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("filter-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_filters_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_filters_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Filter::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3441,106 +3477,115 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advanced-details", "case-sensitive", "created", "exclude-details", "expression-value", "extract-a", "extract-b", "field", "field-a", "field-a-required", "field-b", "field-b-required", "href", "id", "include-details", "kind", "lowercase-details", "match-type", "name", "output-constructor", "output-to-field", "override-output-field", "parent-link", "replace-string", "search-and-replace-details", "search-string", "self-link", "type", "updated", "uppercase-details"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().filters_update(request, &self.opt.arg_account_id, &self.opt.arg_filter_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().filters_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("filter-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_goals_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().goals_get(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id, &self.opt.arg_goal_id); - for parg in self.opt.arg_v.iter() { + fn _management_goals_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().goals_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or(""), opt.value_of("goal-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_goals_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_goals_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Goal::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3681,58 +3726,63 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "case-sensitive", "comparison-type", "comparison-value", "created", "event-details", "first-step-required", "href", "id", "internal-web-property-id", "kind", "match-type", "name", "parent-link", "profile-id", "self-link", "type", "updated", "url", "url-destination-details", "use-event-value", "value", "visit-num-pages-details", "visit-time-on-site-details", "web-property-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().goals_insert(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().goals_insert(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_goals_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().goals_list(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id); - for parg in self.opt.arg_v.iter() { + fn _management_goals_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().goals_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -3741,52 +3791,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_goals_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_goals_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Goal::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3927,60 +3981,65 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "case-sensitive", "comparison-type", "comparison-value", "created", "event-details", "first-step-required", "href", "id", "internal-web-property-id", "kind", "match-type", "name", "parent-link", "profile-id", "self-link", "type", "updated", "url", "url-destination-details", "use-event-value", "value", "visit-num-pages-details", "visit-time-on-site-details", "web-property-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().goals_patch(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id, &self.opt.arg_goal_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().goals_patch(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or(""), opt.value_of("goal-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_goals_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_goals_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Goal::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4121,150 +4180,158 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "case-sensitive", "comparison-type", "comparison-value", "created", "event-details", "first-step-required", "href", "id", "internal-web-property-id", "kind", "match-type", "name", "parent-link", "profile-id", "self-link", "type", "updated", "url", "url-destination-details", "use-event-value", "value", "visit-num-pages-details", "visit-time-on-site-details", "web-property-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().goals_update(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id, &self.opt.arg_goal_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().goals_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or(""), opt.value_of("goal-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_profile_filter_links_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().profile_filter_links_delete(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id, &self.opt.arg_link_id); - for parg in self.opt.arg_v.iter() { + fn _management_profile_filter_links_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().profile_filter_links_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or(""), opt.value_of("link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _management_profile_filter_links_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().profile_filter_links_get(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id, &self.opt.arg_link_id); - for parg in self.opt.arg_v.iter() { + fn _management_profile_filter_links_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().profile_filter_links_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or(""), opt.value_of("link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_profile_filter_links_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_profile_filter_links_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ProfileFilterLink::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4354,58 +4421,63 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "filter-ref", "href", "id", "internal-web-property-id", "kind", "name", "profile-ref", "rank", "self-link", "web-property-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().profile_filter_links_insert(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().profile_filter_links_insert(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_profile_filter_links_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().profile_filter_links_list(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id); - for parg in self.opt.arg_v.iter() { + fn _management_profile_filter_links_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().profile_filter_links_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -4414,52 +4486,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_profile_filter_links_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_profile_filter_links_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ProfileFilterLink::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4549,60 +4625,65 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "filter-ref", "href", "id", "internal-web-property-id", "kind", "name", "profile-ref", "rank", "self-link", "web-property-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().profile_filter_links_patch(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id, &self.opt.arg_link_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().profile_filter_links_patch(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or(""), opt.value_of("link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_profile_filter_links_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_profile_filter_links_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ProfileFilterLink::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4692,104 +4773,108 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "filter-ref", "href", "id", "internal-web-property-id", "kind", "name", "profile-ref", "rank", "self-link", "web-property-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().profile_filter_links_update(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id, &self.opt.arg_link_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().profile_filter_links_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or(""), opt.value_of("link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_profile_user_links_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().profile_user_links_delete(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id, &self.opt.arg_link_id); - for parg in self.opt.arg_v.iter() { + fn _management_profile_user_links_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().profile_user_links_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or(""), opt.value_of("link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _management_profile_user_links_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_profile_user_links_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::EntityUserLink::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4949,58 +5034,63 @@ impl Engine { request.permissions.as_mut().unwrap().effective.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "account-ref", "effective", "email", "entity", "href", "id", "internal-web-property-id", "kind", "local", "name", "permissions", "profile-ref", "self-link", "user-ref", "web-property-id", "web-property-ref"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().profile_user_links_insert(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().profile_user_links_insert(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_profile_user_links_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().profile_user_links_list(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id); - for parg in self.opt.arg_v.iter() { + fn _management_profile_user_links_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().profile_user_links_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -5009,52 +5099,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_profile_user_links_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_profile_user_links_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::EntityUserLink::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -5214,150 +5308,158 @@ impl Engine { request.permissions.as_mut().unwrap().effective.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "account-ref", "effective", "email", "entity", "href", "id", "internal-web-property-id", "kind", "local", "name", "permissions", "profile-ref", "self-link", "user-ref", "web-property-id", "web-property-ref"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().profile_user_links_update(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id, &self.opt.arg_link_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().profile_user_links_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or(""), opt.value_of("link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_profiles_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().profiles_delete(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id); - for parg in self.opt.arg_v.iter() { + fn _management_profiles_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().profiles_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _management_profiles_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().profiles_get(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id); - for parg in self.opt.arg_v.iter() { + fn _management_profiles_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().profiles_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_profiles_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_profiles_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Profile::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -5486,58 +5588,63 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "child-link", "created", "currency", "default-page", "e-commerce-tracking", "effective", "enhanced-e-commerce-tracking", "exclude-query-parameters", "href", "id", "internal-web-property-id", "kind", "name", "parent-link", "permissions", "self-link", "site-search-category-parameters", "site-search-query-parameters", "strip-site-search-category-parameters", "strip-site-search-query-parameters", "timezone", "type", "updated", "web-property-id", "website-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().profiles_insert(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().profiles_insert(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_profiles_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().profiles_list(&self.opt.arg_account_id, &self.opt.arg_web_property_id); - for parg in self.opt.arg_v.iter() { + fn _management_profiles_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().profiles_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -5546,52 +5653,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_profiles_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_profiles_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Profile::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -5720,60 +5831,65 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "child-link", "created", "currency", "default-page", "e-commerce-tracking", "effective", "enhanced-e-commerce-tracking", "exclude-query-parameters", "href", "id", "internal-web-property-id", "kind", "name", "parent-link", "permissions", "self-link", "site-search-category-parameters", "site-search-query-parameters", "strip-site-search-category-parameters", "strip-site-search-query-parameters", "timezone", "type", "updated", "web-property-id", "website-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().profiles_patch(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().profiles_patch(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_profiles_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_profiles_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Profile::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -5902,58 +6018,63 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "child-link", "created", "currency", "default-page", "e-commerce-tracking", "effective", "enhanced-e-commerce-tracking", "exclude-query-parameters", "href", "id", "internal-web-property-id", "kind", "name", "parent-link", "permissions", "self-link", "site-search-category-parameters", "site-search-query-parameters", "strip-site-search-category-parameters", "strip-site-search-query-parameters", "timezone", "type", "updated", "web-property-id", "website-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().profiles_update(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().profiles_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_segments_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_segments_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.management().segments_list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -5962,98 +6083,106 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_unsampled_reports_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().unsampled_reports_get(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id, &self.opt.arg_unsampled_report_id); - for parg in self.opt.arg_v.iter() { + fn _management_unsampled_reports_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().unsampled_reports_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or(""), opt.value_of("unsampled-report-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_unsampled_reports_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_unsampled_reports_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UnsampledReport::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -6159,58 +6288,63 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "bucket-id", "cloud-storage-download-details", "created", "dimensions", "document-id", "download-type", "drive-download-details", "end-date", "filters", "id", "kind", "metrics", "object-id", "profile-id", "segment", "self-link", "start-date", "status", "title", "updated", "web-property-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().unsampled_reports_insert(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().unsampled_reports_insert(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_unsampled_reports_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().unsampled_reports_list(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_profile_id); - for parg in self.opt.arg_v.iter() { + fn _management_unsampled_reports_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().unsampled_reports_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -6219,52 +6353,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_uploads_delete_upload_data(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_uploads_delete_upload_data(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AnalyticsDataimportDeleteUploadDataRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -6286,426 +6424,106 @@ impl Engine { request.custom_data_import_uids.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["custom-data-import-uids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().uploads_delete_upload_data(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_custom_data_source_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().uploads_delete_upload_data(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("custom-data-source-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _management_uploads_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().uploads_get(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_custom_data_source_id, &self.opt.arg_upload_id); - for parg in self.opt.arg_v.iter() { + fn _management_uploads_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().uploads_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("custom-data-source-id").unwrap_or(""), opt.value_of("upload-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _management_uploads_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().uploads_list(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_custom_data_source_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "start-index" => { - call = call.start_index(arg_from_str(value.unwrap_or("-0"), err, "start-index", "integer")); - }, - "max-results" => { - call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); - }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _management_uploads_upload_data(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().uploads_upload_data(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_custom_data_source_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_web_property_ad_words_links_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().web_property_ad_words_links_delete(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_web_property_ad_words_link_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok(mut response) => { - None - } - } - } - } - - fn _management_web_property_ad_words_links_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().web_property_ad_words_links_get(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_web_property_ad_words_link_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _management_web_property_ad_words_links_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - - let mut request = api::EntityAdWordsLink::default(); - let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { - let last_errc = err.issues.len(); - let (key, value) = parse_kv_arg(&*kvarg, err, false); - let mut temp_cursor = field_cursor.clone(); - if let Err(field_err) = temp_cursor.set(&*key) { - err.issues.push(field_err); - } - if value.is_none() { - field_cursor = temp_cursor.clone(); - if err.issues.len() > last_errc { - err.issues.remove(last_errc); - } - continue; - } - fn request_entity_init(request: &mut api::EntityAdWordsLink) { - if request.entity.is_none() { - request.entity = Some(Default::default()); - } - } - - fn request_entity_web_property_ref_init(request: &mut api::EntityAdWordsLink) { - request_entity_init(request); - if request.entity.as_mut().unwrap().web_property_ref.is_none() { - request.entity.as_mut().unwrap().web_property_ref = Some(Default::default()); - } - } - - match &temp_cursor.to_string()[..] { - "kind" => { - request.kind = Some(value.unwrap_or("").to_string()); - }, - "name" => { - request.name = Some(value.unwrap_or("").to_string()); - }, - "profile-ids" => { - if request.profile_ids.is_none() { - request.profile_ids = Some(Default::default()); - } - request.profile_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); - }, - "entity.web-property-ref.kind" => { - request_entity_web_property_ref_init(&mut request); - request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "entity.web-property-ref.name" => { - request_entity_web_property_ref_init(&mut request); - request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().name = Some(value.unwrap_or("").to_string()); - }, - "entity.web-property-ref.internal-web-property-id" => { - request_entity_web_property_ref_init(&mut request); - request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().internal_web_property_id = Some(value.unwrap_or("").to_string()); - }, - "entity.web-property-ref.href" => { - request_entity_web_property_ref_init(&mut request); - request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().href = Some(value.unwrap_or("").to_string()); - }, - "entity.web-property-ref.id" => { - request_entity_web_property_ref_init(&mut request); - request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); - }, - "entity.web-property-ref.account-id" => { - request_entity_web_property_ref_init(&mut request); - request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().account_id = Some(value.unwrap_or("").to_string()); - }, - "id" => { - request_entity_init(&mut request); - request.id = Some(value.unwrap_or("").to_string()); - }, - "self-link" => { - request_entity_init(&mut request); - request.self_link = Some(value.unwrap_or("").to_string()); - }, - _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); - } - } - } - let mut call = self.hub.management().web_property_ad_words_links_insert(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _management_web_property_ad_words_links_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().web_property_ad_words_links_list(&self.opt.arg_account_id, &self.opt.arg_web_property_id); - for parg in self.opt.arg_v.iter() { + fn _management_uploads_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().uploads_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("custom-data-source-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -6714,52 +6532,203 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_web_property_ad_words_links_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_uploads_upload_data(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().uploads_upload_data(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("custom-data-source-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _management_web_property_ad_words_links_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().web_property_ad_words_links_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("web-property-ad-words-link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _management_web_property_ad_words_links_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().web_property_ad_words_links_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("web-property-ad-words-link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _management_web_property_ad_words_links_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::EntityAdWordsLink::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -6832,383 +6801,63 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "entity", "href", "id", "internal-web-property-id", "kind", "name", "profile-ids", "self-link", "web-property-ref"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().web_property_ad_words_links_patch(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_web_property_ad_words_link_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().web_property_ad_words_links_insert(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _management_web_property_ad_words_links_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - - let mut request = api::EntityAdWordsLink::default(); - let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { - let last_errc = err.issues.len(); - let (key, value) = parse_kv_arg(&*kvarg, err, false); - let mut temp_cursor = field_cursor.clone(); - if let Err(field_err) = temp_cursor.set(&*key) { - err.issues.push(field_err); - } - if value.is_none() { - field_cursor = temp_cursor.clone(); - if err.issues.len() > last_errc { - err.issues.remove(last_errc); - } - continue; - } - fn request_entity_init(request: &mut api::EntityAdWordsLink) { - if request.entity.is_none() { - request.entity = Some(Default::default()); - } - } - - fn request_entity_web_property_ref_init(request: &mut api::EntityAdWordsLink) { - request_entity_init(request); - if request.entity.as_mut().unwrap().web_property_ref.is_none() { - request.entity.as_mut().unwrap().web_property_ref = Some(Default::default()); - } - } - - match &temp_cursor.to_string()[..] { - "kind" => { - request.kind = Some(value.unwrap_or("").to_string()); - }, - "name" => { - request.name = Some(value.unwrap_or("").to_string()); - }, - "profile-ids" => { - if request.profile_ids.is_none() { - request.profile_ids = Some(Default::default()); - } - request.profile_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); - }, - "entity.web-property-ref.kind" => { - request_entity_web_property_ref_init(&mut request); - request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "entity.web-property-ref.name" => { - request_entity_web_property_ref_init(&mut request); - request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().name = Some(value.unwrap_or("").to_string()); - }, - "entity.web-property-ref.internal-web-property-id" => { - request_entity_web_property_ref_init(&mut request); - request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().internal_web_property_id = Some(value.unwrap_or("").to_string()); - }, - "entity.web-property-ref.href" => { - request_entity_web_property_ref_init(&mut request); - request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().href = Some(value.unwrap_or("").to_string()); - }, - "entity.web-property-ref.id" => { - request_entity_web_property_ref_init(&mut request); - request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); - }, - "entity.web-property-ref.account-id" => { - request_entity_web_property_ref_init(&mut request); - request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().account_id = Some(value.unwrap_or("").to_string()); - }, - "id" => { - request_entity_init(&mut request); - request.id = Some(value.unwrap_or("").to_string()); - }, - "self-link" => { - request_entity_init(&mut request); - request.self_link = Some(value.unwrap_or("").to_string()); - }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); - } - } - } - let mut call = self.hub.management().web_property_ad_words_links_update(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_web_property_ad_words_link_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _management_webproperties_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().webproperties_get(&self.opt.arg_account_id, &self.opt.arg_web_property_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _management_webproperties_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - - let mut request = api::Webproperty::default(); - let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { - let last_errc = err.issues.len(); - let (key, value) = parse_kv_arg(&*kvarg, err, false); - let mut temp_cursor = field_cursor.clone(); - if let Err(field_err) = temp_cursor.set(&*key) { - err.issues.push(field_err); - } - if value.is_none() { - field_cursor = temp_cursor.clone(); - if err.issues.len() > last_errc { - err.issues.remove(last_errc); - } - continue; - } - fn request_child_link_init(request: &mut api::Webproperty) { - if request.child_link.is_none() { - request.child_link = Some(Default::default()); - } - } - - fn request_parent_link_init(request: &mut api::Webproperty) { - if request.parent_link.is_none() { - request.parent_link = Some(Default::default()); - } - } - - fn request_permissions_init(request: &mut api::Webproperty) { - if request.permissions.is_none() { - request.permissions = Some(Default::default()); - } - } - - match &temp_cursor.to_string()[..] { - "website-url" => { - request.website_url = Some(value.unwrap_or("").to_string()); - }, - "updated" => { - request.updated = Some(value.unwrap_or("").to_string()); - }, - "name" => { - request.name = Some(value.unwrap_or("").to_string()); - }, - "created" => { - request.created = Some(value.unwrap_or("").to_string()); - }, - "default-profile-id" => { - request.default_profile_id = Some(value.unwrap_or("").to_string()); - }, - "level" => { - request.level = Some(value.unwrap_or("").to_string()); - }, - "kind" => { - request.kind = Some(value.unwrap_or("").to_string()); - }, - "profile-count" => { - request.profile_count = Some(arg_from_str(value.unwrap_or("-0"), err, "profile-count", "integer")); - }, - "internal-web-property-id" => { - request.internal_web_property_id = Some(value.unwrap_or("").to_string()); - }, - "child-link.href" => { - request_child_link_init(&mut request); - request.child_link.as_mut().unwrap().href = Some(value.unwrap_or("").to_string()); - }, - "child-link.type" => { - request_child_link_init(&mut request); - request.child_link.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); - }, - "industry-vertical" => { - request_child_link_init(&mut request); - request.industry_vertical = Some(value.unwrap_or("").to_string()); - }, - "parent-link.href" => { - request_parent_link_init(&mut request); - request.parent_link.as_mut().unwrap().href = Some(value.unwrap_or("").to_string()); - }, - "parent-link.type" => { - request_parent_link_init(&mut request); - request.parent_link.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); - }, - "permissions.effective" => { - request_permissions_init(&mut request); - if request.permissions.as_mut().unwrap().effective.is_none() { - request.permissions.as_mut().unwrap().effective = Some(Default::default()); + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; } - request.permissions.as_mut().unwrap().effective.as_mut().unwrap().push(value.unwrap_or("").to_string()); - }, - "id" => { - request_permissions_init(&mut request); - request.id = Some(value.unwrap_or("").to_string()); - }, - "self-link" => { - request_permissions_init(&mut request); - request.self_link = Some(value.unwrap_or("").to_string()); - }, - "account-id" => { - request_permissions_init(&mut request); - request.account_id = Some(value.unwrap_or("").to_string()); - }, - _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } } } } - let mut call = self.hub.management().webproperties_insert(request, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_webproperties_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().webproperties_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _management_web_property_ad_words_links_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().web_property_ad_words_links_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -7217,52 +6866,368 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_webproperties_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_web_property_ad_words_links_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::EntityAdWordsLink::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_entity_init(request: &mut api::EntityAdWordsLink) { + if request.entity.is_none() { + request.entity = Some(Default::default()); + } + } + + fn request_entity_web_property_ref_init(request: &mut api::EntityAdWordsLink) { + request_entity_init(request); + if request.entity.as_mut().unwrap().web_property_ref.is_none() { + request.entity.as_mut().unwrap().web_property_ref = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "profile-ids" => { + if request.profile_ids.is_none() { + request.profile_ids = Some(Default::default()); + } + request.profile_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "entity.web-property-ref.kind" => { + request_entity_web_property_ref_init(&mut request); + request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "entity.web-property-ref.name" => { + request_entity_web_property_ref_init(&mut request); + request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().name = Some(value.unwrap_or("").to_string()); + }, + "entity.web-property-ref.internal-web-property-id" => { + request_entity_web_property_ref_init(&mut request); + request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().internal_web_property_id = Some(value.unwrap_or("").to_string()); + }, + "entity.web-property-ref.href" => { + request_entity_web_property_ref_init(&mut request); + request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().href = Some(value.unwrap_or("").to_string()); + }, + "entity.web-property-ref.id" => { + request_entity_web_property_ref_init(&mut request); + request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "entity.web-property-ref.account-id" => { + request_entity_web_property_ref_init(&mut request); + request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().account_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_entity_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "self-link" => { + request_entity_init(&mut request); + request.self_link = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "entity", "href", "id", "internal-web-property-id", "kind", "name", "profile-ids", "self-link", "web-property-ref"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.management().web_property_ad_words_links_patch(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("web-property-ad-words-link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _management_web_property_ad_words_links_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::EntityAdWordsLink::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_entity_init(request: &mut api::EntityAdWordsLink) { + if request.entity.is_none() { + request.entity = Some(Default::default()); + } + } + + fn request_entity_web_property_ref_init(request: &mut api::EntityAdWordsLink) { + request_entity_init(request); + if request.entity.as_mut().unwrap().web_property_ref.is_none() { + request.entity.as_mut().unwrap().web_property_ref = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "profile-ids" => { + if request.profile_ids.is_none() { + request.profile_ids = Some(Default::default()); + } + request.profile_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "entity.web-property-ref.kind" => { + request_entity_web_property_ref_init(&mut request); + request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "entity.web-property-ref.name" => { + request_entity_web_property_ref_init(&mut request); + request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().name = Some(value.unwrap_or("").to_string()); + }, + "entity.web-property-ref.internal-web-property-id" => { + request_entity_web_property_ref_init(&mut request); + request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().internal_web_property_id = Some(value.unwrap_or("").to_string()); + }, + "entity.web-property-ref.href" => { + request_entity_web_property_ref_init(&mut request); + request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().href = Some(value.unwrap_or("").to_string()); + }, + "entity.web-property-ref.id" => { + request_entity_web_property_ref_init(&mut request); + request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "entity.web-property-ref.account-id" => { + request_entity_web_property_ref_init(&mut request); + request.entity.as_mut().unwrap().web_property_ref.as_mut().unwrap().account_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_entity_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "self-link" => { + request_entity_init(&mut request); + request.self_link = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "entity", "href", "id", "internal-web-property-id", "kind", "name", "profile-ids", "self-link", "web-property-ref"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.management().web_property_ad_words_links_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("web-property-ad-words-link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _management_webproperties_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().webproperties_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _management_webproperties_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Webproperty::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -7362,60 +7327,121 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "child-link", "created", "default-profile-id", "effective", "href", "id", "industry-vertical", "internal-web-property-id", "kind", "level", "name", "parent-link", "permissions", "profile-count", "self-link", "type", "updated", "website-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().webproperties_patch(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().webproperties_insert(request, opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_webproperties_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_webproperties_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().webproperties_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "start-index" => { + call = call.start_index(arg_from_str(value.unwrap_or("-0"), err, "start-index", "integer")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _management_webproperties_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Webproperty::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -7515,104 +7541,266 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "child-link", "created", "default-profile-id", "effective", "href", "id", "industry-vertical", "internal-web-property-id", "kind", "level", "name", "parent-link", "permissions", "profile-count", "self-link", "type", "updated", "website-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().webproperties_update(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().webproperties_patch(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_webproperty_user_links_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().webproperty_user_links_delete(&self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_link_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + fn _management_webproperties_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Webproperty::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_child_link_init(request: &mut api::Webproperty) { + if request.child_link.is_none() { + request.child_link = Some(Default::default()); + } + } + + fn request_parent_link_init(request: &mut api::Webproperty) { + if request.parent_link.is_none() { + request.parent_link = Some(Default::default()); + } + } + + fn request_permissions_init(request: &mut api::Webproperty) { + if request.permissions.is_none() { + request.permissions = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "website-url" => { + request.website_url = Some(value.unwrap_or("").to_string()); + }, + "updated" => { + request.updated = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "created" => { + request.created = Some(value.unwrap_or("").to_string()); + }, + "default-profile-id" => { + request.default_profile_id = Some(value.unwrap_or("").to_string()); + }, + "level" => { + request.level = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "profile-count" => { + request.profile_count = Some(arg_from_str(value.unwrap_or("-0"), err, "profile-count", "integer")); + }, + "internal-web-property-id" => { + request.internal_web_property_id = Some(value.unwrap_or("").to_string()); + }, + "child-link.href" => { + request_child_link_init(&mut request); + request.child_link.as_mut().unwrap().href = Some(value.unwrap_or("").to_string()); + }, + "child-link.type" => { + request_child_link_init(&mut request); + request.child_link.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); + }, + "industry-vertical" => { + request_child_link_init(&mut request); + request.industry_vertical = Some(value.unwrap_or("").to_string()); + }, + "parent-link.href" => { + request_parent_link_init(&mut request); + request.parent_link.as_mut().unwrap().href = Some(value.unwrap_or("").to_string()); + }, + "parent-link.type" => { + request_parent_link_init(&mut request); + request.parent_link.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); + }, + "permissions.effective" => { + request_permissions_init(&mut request); + if request.permissions.as_mut().unwrap().effective.is_none() { + request.permissions.as_mut().unwrap().effective = Some(Default::default()); + } + request.permissions.as_mut().unwrap().effective.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "id" => { + request_permissions_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "self-link" => { + request_permissions_init(&mut request); + request.self_link = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_permissions_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "child-link", "created", "default-profile-id", "effective", "href", "id", "industry-vertical", "internal-web-property-id", "kind", "level", "name", "parent-link", "permissions", "profile-count", "self-link", "type", "updated", "website-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } } } - let protocol = "standard-request"; + let mut call = self.hub.management().webproperties_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _management_webproperty_user_links_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().webproperty_user_links_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _management_webproperty_user_links_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_webproperty_user_links_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::EntityUserLink::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -7772,58 +7960,63 @@ impl Engine { request.permissions.as_mut().unwrap().effective.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "account-ref", "effective", "email", "entity", "href", "id", "internal-web-property-id", "kind", "local", "name", "permissions", "profile-ref", "self-link", "user-ref", "web-property-id", "web-property-ref"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().webproperty_user_links_insert(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().webproperty_user_links_insert(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_webproperty_user_links_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.management().webproperty_user_links_list(&self.opt.arg_account_id, &self.opt.arg_web_property_id); - for parg in self.opt.arg_v.iter() { + fn _management_webproperty_user_links_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.management().webproperty_user_links_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -7832,52 +8025,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _management_webproperty_user_links_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _management_webproperty_user_links_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::EntityUserLink::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -8037,106 +8234,115 @@ impl Engine { request.permissions.as_mut().unwrap().effective.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "account-ref", "effective", "email", "entity", "href", "id", "internal-web-property-id", "kind", "local", "name", "permissions", "profile-ref", "self-link", "user-ref", "web-property-id", "web-property-ref"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.management().webproperty_user_links_update(request, &self.opt.arg_account_id, &self.opt.arg_web_property_id, &self.opt.arg_link_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.management().webproperty_user_links_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("web-property-id").unwrap_or(""), opt.value_of("link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _metadata_columns_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.metadata().columns_list(&self.opt.arg_report_type); - for parg in self.opt.arg_v.iter() { + fn _metadata_columns_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.metadata().columns_list(opt.value_of("report-type").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _provisioning_create_account_ticket(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _provisioning_create_account_ticket(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AccountTicket::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -8459,250 +8665,350 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account", "account-id", "child-link", "created", "currency", "default-page", "default-profile-id", "e-commerce-tracking", "effective", "enhanced-e-commerce-tracking", "exclude-query-parameters", "href", "id", "industry-vertical", "internal-web-property-id", "kind", "level", "name", "parent-link", "permissions", "profile", "profile-count", "redirect-uri", "self-link", "site-search-category-parameters", "site-search-query-parameters", "strip-site-search-category-parameters", "strip-site-search-query-parameters", "timezone", "type", "updated", "web-property-id", "webproperty", "website-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.provisioning().create_account_ticket(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_data { - if self.opt.cmd_ga_get { - call_result = self._data_ga_get(dry_run, &mut err); - } else if self.opt.cmd_mcf_get { - call_result = self._data_mcf_get(dry_run, &mut err); - } else if self.opt.cmd_realtime_get { - call_result = self._data_realtime_get(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("data", Some(opt)) => { + match opt.subcommand() { + ("ga-get", Some(opt)) => { + call_result = self._data_ga_get(opt, dry_run, &mut err); + }, + ("mcf-get", Some(opt)) => { + call_result = self._data_mcf_get(opt, dry_run, &mut err); + }, + ("realtime-get", Some(opt)) => { + call_result = self._data_realtime_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("data".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("management", Some(opt)) => { + match opt.subcommand() { + ("account-summaries-list", Some(opt)) => { + call_result = self._management_account_summaries_list(opt, dry_run, &mut err); + }, + ("account-user-links-delete", Some(opt)) => { + call_result = self._management_account_user_links_delete(opt, dry_run, &mut err); + }, + ("account-user-links-insert", Some(opt)) => { + call_result = self._management_account_user_links_insert(opt, dry_run, &mut err); + }, + ("account-user-links-list", Some(opt)) => { + call_result = self._management_account_user_links_list(opt, dry_run, &mut err); + }, + ("account-user-links-update", Some(opt)) => { + call_result = self._management_account_user_links_update(opt, dry_run, &mut err); + }, + ("accounts-list", Some(opt)) => { + call_result = self._management_accounts_list(opt, dry_run, &mut err); + }, + ("custom-data-sources-list", Some(opt)) => { + call_result = self._management_custom_data_sources_list(opt, dry_run, &mut err); + }, + ("custom-dimensions-get", Some(opt)) => { + call_result = self._management_custom_dimensions_get(opt, dry_run, &mut err); + }, + ("custom-dimensions-insert", Some(opt)) => { + call_result = self._management_custom_dimensions_insert(opt, dry_run, &mut err); + }, + ("custom-dimensions-list", Some(opt)) => { + call_result = self._management_custom_dimensions_list(opt, dry_run, &mut err); + }, + ("custom-dimensions-patch", Some(opt)) => { + call_result = self._management_custom_dimensions_patch(opt, dry_run, &mut err); + }, + ("custom-dimensions-update", Some(opt)) => { + call_result = self._management_custom_dimensions_update(opt, dry_run, &mut err); + }, + ("custom-metrics-get", Some(opt)) => { + call_result = self._management_custom_metrics_get(opt, dry_run, &mut err); + }, + ("custom-metrics-insert", Some(opt)) => { + call_result = self._management_custom_metrics_insert(opt, dry_run, &mut err); + }, + ("custom-metrics-list", Some(opt)) => { + call_result = self._management_custom_metrics_list(opt, dry_run, &mut err); + }, + ("custom-metrics-patch", Some(opt)) => { + call_result = self._management_custom_metrics_patch(opt, dry_run, &mut err); + }, + ("custom-metrics-update", Some(opt)) => { + call_result = self._management_custom_metrics_update(opt, dry_run, &mut err); + }, + ("experiments-delete", Some(opt)) => { + call_result = self._management_experiments_delete(opt, dry_run, &mut err); + }, + ("experiments-get", Some(opt)) => { + call_result = self._management_experiments_get(opt, dry_run, &mut err); + }, + ("experiments-insert", Some(opt)) => { + call_result = self._management_experiments_insert(opt, dry_run, &mut err); + }, + ("experiments-list", Some(opt)) => { + call_result = self._management_experiments_list(opt, dry_run, &mut err); + }, + ("experiments-patch", Some(opt)) => { + call_result = self._management_experiments_patch(opt, dry_run, &mut err); + }, + ("experiments-update", Some(opt)) => { + call_result = self._management_experiments_update(opt, dry_run, &mut err); + }, + ("filters-delete", Some(opt)) => { + call_result = self._management_filters_delete(opt, dry_run, &mut err); + }, + ("filters-get", Some(opt)) => { + call_result = self._management_filters_get(opt, dry_run, &mut err); + }, + ("filters-insert", Some(opt)) => { + call_result = self._management_filters_insert(opt, dry_run, &mut err); + }, + ("filters-list", Some(opt)) => { + call_result = self._management_filters_list(opt, dry_run, &mut err); + }, + ("filters-patch", Some(opt)) => { + call_result = self._management_filters_patch(opt, dry_run, &mut err); + }, + ("filters-update", Some(opt)) => { + call_result = self._management_filters_update(opt, dry_run, &mut err); + }, + ("goals-get", Some(opt)) => { + call_result = self._management_goals_get(opt, dry_run, &mut err); + }, + ("goals-insert", Some(opt)) => { + call_result = self._management_goals_insert(opt, dry_run, &mut err); + }, + ("goals-list", Some(opt)) => { + call_result = self._management_goals_list(opt, dry_run, &mut err); + }, + ("goals-patch", Some(opt)) => { + call_result = self._management_goals_patch(opt, dry_run, &mut err); + }, + ("goals-update", Some(opt)) => { + call_result = self._management_goals_update(opt, dry_run, &mut err); + }, + ("profile-filter-links-delete", Some(opt)) => { + call_result = self._management_profile_filter_links_delete(opt, dry_run, &mut err); + }, + ("profile-filter-links-get", Some(opt)) => { + call_result = self._management_profile_filter_links_get(opt, dry_run, &mut err); + }, + ("profile-filter-links-insert", Some(opt)) => { + call_result = self._management_profile_filter_links_insert(opt, dry_run, &mut err); + }, + ("profile-filter-links-list", Some(opt)) => { + call_result = self._management_profile_filter_links_list(opt, dry_run, &mut err); + }, + ("profile-filter-links-patch", Some(opt)) => { + call_result = self._management_profile_filter_links_patch(opt, dry_run, &mut err); + }, + ("profile-filter-links-update", Some(opt)) => { + call_result = self._management_profile_filter_links_update(opt, dry_run, &mut err); + }, + ("profile-user-links-delete", Some(opt)) => { + call_result = self._management_profile_user_links_delete(opt, dry_run, &mut err); + }, + ("profile-user-links-insert", Some(opt)) => { + call_result = self._management_profile_user_links_insert(opt, dry_run, &mut err); + }, + ("profile-user-links-list", Some(opt)) => { + call_result = self._management_profile_user_links_list(opt, dry_run, &mut err); + }, + ("profile-user-links-update", Some(opt)) => { + call_result = self._management_profile_user_links_update(opt, dry_run, &mut err); + }, + ("profiles-delete", Some(opt)) => { + call_result = self._management_profiles_delete(opt, dry_run, &mut err); + }, + ("profiles-get", Some(opt)) => { + call_result = self._management_profiles_get(opt, dry_run, &mut err); + }, + ("profiles-insert", Some(opt)) => { + call_result = self._management_profiles_insert(opt, dry_run, &mut err); + }, + ("profiles-list", Some(opt)) => { + call_result = self._management_profiles_list(opt, dry_run, &mut err); + }, + ("profiles-patch", Some(opt)) => { + call_result = self._management_profiles_patch(opt, dry_run, &mut err); + }, + ("profiles-update", Some(opt)) => { + call_result = self._management_profiles_update(opt, dry_run, &mut err); + }, + ("segments-list", Some(opt)) => { + call_result = self._management_segments_list(opt, dry_run, &mut err); + }, + ("unsampled-reports-get", Some(opt)) => { + call_result = self._management_unsampled_reports_get(opt, dry_run, &mut err); + }, + ("unsampled-reports-insert", Some(opt)) => { + call_result = self._management_unsampled_reports_insert(opt, dry_run, &mut err); + }, + ("unsampled-reports-list", Some(opt)) => { + call_result = self._management_unsampled_reports_list(opt, dry_run, &mut err); + }, + ("uploads-delete-upload-data", Some(opt)) => { + call_result = self._management_uploads_delete_upload_data(opt, dry_run, &mut err); + }, + ("uploads-get", Some(opt)) => { + call_result = self._management_uploads_get(opt, dry_run, &mut err); + }, + ("uploads-list", Some(opt)) => { + call_result = self._management_uploads_list(opt, dry_run, &mut err); + }, + ("uploads-upload-data", Some(opt)) => { + call_result = self._management_uploads_upload_data(opt, dry_run, &mut err); + }, + ("web-property-ad-words-links-delete", Some(opt)) => { + call_result = self._management_web_property_ad_words_links_delete(opt, dry_run, &mut err); + }, + ("web-property-ad-words-links-get", Some(opt)) => { + call_result = self._management_web_property_ad_words_links_get(opt, dry_run, &mut err); + }, + ("web-property-ad-words-links-insert", Some(opt)) => { + call_result = self._management_web_property_ad_words_links_insert(opt, dry_run, &mut err); + }, + ("web-property-ad-words-links-list", Some(opt)) => { + call_result = self._management_web_property_ad_words_links_list(opt, dry_run, &mut err); + }, + ("web-property-ad-words-links-patch", Some(opt)) => { + call_result = self._management_web_property_ad_words_links_patch(opt, dry_run, &mut err); + }, + ("web-property-ad-words-links-update", Some(opt)) => { + call_result = self._management_web_property_ad_words_links_update(opt, dry_run, &mut err); + }, + ("webproperties-get", Some(opt)) => { + call_result = self._management_webproperties_get(opt, dry_run, &mut err); + }, + ("webproperties-insert", Some(opt)) => { + call_result = self._management_webproperties_insert(opt, dry_run, &mut err); + }, + ("webproperties-list", Some(opt)) => { + call_result = self._management_webproperties_list(opt, dry_run, &mut err); + }, + ("webproperties-patch", Some(opt)) => { + call_result = self._management_webproperties_patch(opt, dry_run, &mut err); + }, + ("webproperties-update", Some(opt)) => { + call_result = self._management_webproperties_update(opt, dry_run, &mut err); + }, + ("webproperty-user-links-delete", Some(opt)) => { + call_result = self._management_webproperty_user_links_delete(opt, dry_run, &mut err); + }, + ("webproperty-user-links-insert", Some(opt)) => { + call_result = self._management_webproperty_user_links_insert(opt, dry_run, &mut err); + }, + ("webproperty-user-links-list", Some(opt)) => { + call_result = self._management_webproperty_user_links_list(opt, dry_run, &mut err); + }, + ("webproperty-user-links-update", Some(opt)) => { + call_result = self._management_webproperty_user_links_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("management".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("metadata", Some(opt)) => { + match opt.subcommand() { + ("columns-list", Some(opt)) => { + call_result = self._metadata_columns_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("metadata".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("provisioning", Some(opt)) => { + match opt.subcommand() { + ("create-account-ticket", Some(opt)) => { + call_result = self._provisioning_create_account_ticket(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("provisioning".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_management { - if self.opt.cmd_account_summaries_list { - call_result = self._management_account_summaries_list(dry_run, &mut err); - } else if self.opt.cmd_account_user_links_delete { - call_result = self._management_account_user_links_delete(dry_run, &mut err); - } else if self.opt.cmd_account_user_links_insert { - call_result = self._management_account_user_links_insert(dry_run, &mut err); - } else if self.opt.cmd_account_user_links_list { - call_result = self._management_account_user_links_list(dry_run, &mut err); - } else if self.opt.cmd_account_user_links_update { - call_result = self._management_account_user_links_update(dry_run, &mut err); - } else if self.opt.cmd_accounts_list { - call_result = self._management_accounts_list(dry_run, &mut err); - } else if self.opt.cmd_custom_data_sources_list { - call_result = self._management_custom_data_sources_list(dry_run, &mut err); - } else if self.opt.cmd_custom_dimensions_get { - call_result = self._management_custom_dimensions_get(dry_run, &mut err); - } else if self.opt.cmd_custom_dimensions_insert { - call_result = self._management_custom_dimensions_insert(dry_run, &mut err); - } else if self.opt.cmd_custom_dimensions_list { - call_result = self._management_custom_dimensions_list(dry_run, &mut err); - } else if self.opt.cmd_custom_dimensions_patch { - call_result = self._management_custom_dimensions_patch(dry_run, &mut err); - } else if self.opt.cmd_custom_dimensions_update { - call_result = self._management_custom_dimensions_update(dry_run, &mut err); - } else if self.opt.cmd_custom_metrics_get { - call_result = self._management_custom_metrics_get(dry_run, &mut err); - } else if self.opt.cmd_custom_metrics_insert { - call_result = self._management_custom_metrics_insert(dry_run, &mut err); - } else if self.opt.cmd_custom_metrics_list { - call_result = self._management_custom_metrics_list(dry_run, &mut err); - } else if self.opt.cmd_custom_metrics_patch { - call_result = self._management_custom_metrics_patch(dry_run, &mut err); - } else if self.opt.cmd_custom_metrics_update { - call_result = self._management_custom_metrics_update(dry_run, &mut err); - } else if self.opt.cmd_experiments_delete { - call_result = self._management_experiments_delete(dry_run, &mut err); - } else if self.opt.cmd_experiments_get { - call_result = self._management_experiments_get(dry_run, &mut err); - } else if self.opt.cmd_experiments_insert { - call_result = self._management_experiments_insert(dry_run, &mut err); - } else if self.opt.cmd_experiments_list { - call_result = self._management_experiments_list(dry_run, &mut err); - } else if self.opt.cmd_experiments_patch { - call_result = self._management_experiments_patch(dry_run, &mut err); - } else if self.opt.cmd_experiments_update { - call_result = self._management_experiments_update(dry_run, &mut err); - } else if self.opt.cmd_filters_delete { - call_result = self._management_filters_delete(dry_run, &mut err); - } else if self.opt.cmd_filters_get { - call_result = self._management_filters_get(dry_run, &mut err); - } else if self.opt.cmd_filters_insert { - call_result = self._management_filters_insert(dry_run, &mut err); - } else if self.opt.cmd_filters_list { - call_result = self._management_filters_list(dry_run, &mut err); - } else if self.opt.cmd_filters_patch { - call_result = self._management_filters_patch(dry_run, &mut err); - } else if self.opt.cmd_filters_update { - call_result = self._management_filters_update(dry_run, &mut err); - } else if self.opt.cmd_goals_get { - call_result = self._management_goals_get(dry_run, &mut err); - } else if self.opt.cmd_goals_insert { - call_result = self._management_goals_insert(dry_run, &mut err); - } else if self.opt.cmd_goals_list { - call_result = self._management_goals_list(dry_run, &mut err); - } else if self.opt.cmd_goals_patch { - call_result = self._management_goals_patch(dry_run, &mut err); - } else if self.opt.cmd_goals_update { - call_result = self._management_goals_update(dry_run, &mut err); - } else if self.opt.cmd_profile_filter_links_delete { - call_result = self._management_profile_filter_links_delete(dry_run, &mut err); - } else if self.opt.cmd_profile_filter_links_get { - call_result = self._management_profile_filter_links_get(dry_run, &mut err); - } else if self.opt.cmd_profile_filter_links_insert { - call_result = self._management_profile_filter_links_insert(dry_run, &mut err); - } else if self.opt.cmd_profile_filter_links_list { - call_result = self._management_profile_filter_links_list(dry_run, &mut err); - } else if self.opt.cmd_profile_filter_links_patch { - call_result = self._management_profile_filter_links_patch(dry_run, &mut err); - } else if self.opt.cmd_profile_filter_links_update { - call_result = self._management_profile_filter_links_update(dry_run, &mut err); - } else if self.opt.cmd_profile_user_links_delete { - call_result = self._management_profile_user_links_delete(dry_run, &mut err); - } else if self.opt.cmd_profile_user_links_insert { - call_result = self._management_profile_user_links_insert(dry_run, &mut err); - } else if self.opt.cmd_profile_user_links_list { - call_result = self._management_profile_user_links_list(dry_run, &mut err); - } else if self.opt.cmd_profile_user_links_update { - call_result = self._management_profile_user_links_update(dry_run, &mut err); - } else if self.opt.cmd_profiles_delete { - call_result = self._management_profiles_delete(dry_run, &mut err); - } else if self.opt.cmd_profiles_get { - call_result = self._management_profiles_get(dry_run, &mut err); - } else if self.opt.cmd_profiles_insert { - call_result = self._management_profiles_insert(dry_run, &mut err); - } else if self.opt.cmd_profiles_list { - call_result = self._management_profiles_list(dry_run, &mut err); - } else if self.opt.cmd_profiles_patch { - call_result = self._management_profiles_patch(dry_run, &mut err); - } else if self.opt.cmd_profiles_update { - call_result = self._management_profiles_update(dry_run, &mut err); - } else if self.opt.cmd_segments_list { - call_result = self._management_segments_list(dry_run, &mut err); - } else if self.opt.cmd_unsampled_reports_get { - call_result = self._management_unsampled_reports_get(dry_run, &mut err); - } else if self.opt.cmd_unsampled_reports_insert { - call_result = self._management_unsampled_reports_insert(dry_run, &mut err); - } else if self.opt.cmd_unsampled_reports_list { - call_result = self._management_unsampled_reports_list(dry_run, &mut err); - } else if self.opt.cmd_uploads_delete_upload_data { - call_result = self._management_uploads_delete_upload_data(dry_run, &mut err); - } else if self.opt.cmd_uploads_get { - call_result = self._management_uploads_get(dry_run, &mut err); - } else if self.opt.cmd_uploads_list { - call_result = self._management_uploads_list(dry_run, &mut err); - } else if self.opt.cmd_uploads_upload_data { - call_result = self._management_uploads_upload_data(dry_run, &mut err); - } else if self.opt.cmd_web_property_ad_words_links_delete { - call_result = self._management_web_property_ad_words_links_delete(dry_run, &mut err); - } else if self.opt.cmd_web_property_ad_words_links_get { - call_result = self._management_web_property_ad_words_links_get(dry_run, &mut err); - } else if self.opt.cmd_web_property_ad_words_links_insert { - call_result = self._management_web_property_ad_words_links_insert(dry_run, &mut err); - } else if self.opt.cmd_web_property_ad_words_links_list { - call_result = self._management_web_property_ad_words_links_list(dry_run, &mut err); - } else if self.opt.cmd_web_property_ad_words_links_patch { - call_result = self._management_web_property_ad_words_links_patch(dry_run, &mut err); - } else if self.opt.cmd_web_property_ad_words_links_update { - call_result = self._management_web_property_ad_words_links_update(dry_run, &mut err); - } else if self.opt.cmd_webproperties_get { - call_result = self._management_webproperties_get(dry_run, &mut err); - } else if self.opt.cmd_webproperties_insert { - call_result = self._management_webproperties_insert(dry_run, &mut err); - } else if self.opt.cmd_webproperties_list { - call_result = self._management_webproperties_list(dry_run, &mut err); - } else if self.opt.cmd_webproperties_patch { - call_result = self._management_webproperties_patch(dry_run, &mut err); - } else if self.opt.cmd_webproperties_update { - call_result = self._management_webproperties_update(dry_run, &mut err); - } else if self.opt.cmd_webproperty_user_links_delete { - call_result = self._management_webproperty_user_links_delete(dry_run, &mut err); - } else if self.opt.cmd_webproperty_user_links_insert { - call_result = self._management_webproperty_user_links_insert(dry_run, &mut err); - } else if self.opt.cmd_webproperty_user_links_list { - call_result = self._management_webproperty_user_links_list(dry_run, &mut err); - } else if self.opt.cmd_webproperty_user_links_update { - call_result = self._management_webproperty_user_links_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_metadata { - if self.opt.cmd_columns_list { - call_result = self._metadata_columns_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_provisioning { - if self.opt.cmd_create_account_ticket { - call_result = self._provisioning_create_account_ticket(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -8715,7 +9021,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -8728,7 +9034,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -8738,37 +9044,2793 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Analytics::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let upload_value_names = ["mode", "file"]; + let arg_data = [ + ("data", "methods: 'ga-get', 'mcf-get' and 'realtime-get'", vec![ + ("ga-get", + Some(r##"Returns Analytics data for a view (profile)."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/data_ga-get", + vec![ + (Some(r##"ids"##), + None, + Some(r##"Unique table ID for retrieving Analytics data. Table ID is of the form ga:XXXX, where XXXX is the Analytics view (profile) ID."##), + Some(true), + Some(false)), + + (Some(r##"start-date"##), + None, + Some(r##"Start date for fetching Analytics data. Requests can specify a start date formatted as YYYY-MM-DD, or as a relative date (e.g., today, yesterday, or 7daysAgo). The default value is 7daysAgo."##), + Some(true), + Some(false)), + + (Some(r##"end-date"##), + None, + Some(r##"End date for fetching Analytics data. Request can should specify an end date formatted as YYYY-MM-DD, or as a relative date (e.g., today, yesterday, or 7daysAgo). The default value is yesterday."##), + Some(true), + Some(false)), + + (Some(r##"metrics"##), + None, + Some(r##"A comma-separated list of Analytics metrics. E.g., 'ga:sessions,ga:pageviews'. At least one metric must be specified."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("mcf-get", + Some(r##"Returns Analytics Multi-Channel Funnels data for a view (profile)."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/data_mcf-get", + vec![ + (Some(r##"ids"##), + None, + Some(r##"Unique table ID for retrieving Analytics data. Table ID is of the form ga:XXXX, where XXXX is the Analytics view (profile) ID."##), + Some(true), + Some(false)), + + (Some(r##"start-date"##), + None, + Some(r##"Start date for fetching Analytics data. Requests can specify a start date formatted as YYYY-MM-DD, or as a relative date (e.g., today, yesterday, or 7daysAgo). The default value is 7daysAgo."##), + Some(true), + Some(false)), + + (Some(r##"end-date"##), + None, + Some(r##"End date for fetching Analytics data. Requests can specify a start date formatted as YYYY-MM-DD, or as a relative date (e.g., today, yesterday, or 7daysAgo). The default value is 7daysAgo."##), + Some(true), + Some(false)), + + (Some(r##"metrics"##), + None, + Some(r##"A comma-separated list of Multi-Channel Funnels metrics. E.g., 'mcf:totalConversions,mcf:totalConversionValue'. At least one metric must be specified."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("realtime-get", + Some(r##"Returns real time data for a view (profile)."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/data_realtime-get", + vec![ + (Some(r##"ids"##), + None, + Some(r##"Unique table ID for retrieving real time data. Table ID is of the form ga:XXXX, where XXXX is the Analytics view (profile) ID."##), + Some(true), + Some(false)), + + (Some(r##"metrics"##), + None, + Some(r##"A comma-separated list of real time metrics. E.g., 'rt:activeUsers'. At least one metric must be specified."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("management", "methods: 'account-summaries-list', 'account-user-links-delete', 'account-user-links-insert', 'account-user-links-list', 'account-user-links-update', 'accounts-list', 'custom-data-sources-list', 'custom-dimensions-get', 'custom-dimensions-insert', 'custom-dimensions-list', 'custom-dimensions-patch', 'custom-dimensions-update', 'custom-metrics-get', 'custom-metrics-insert', 'custom-metrics-list', 'custom-metrics-patch', 'custom-metrics-update', 'experiments-delete', 'experiments-get', 'experiments-insert', 'experiments-list', 'experiments-patch', 'experiments-update', 'filters-delete', 'filters-get', 'filters-insert', 'filters-list', 'filters-patch', 'filters-update', 'goals-get', 'goals-insert', 'goals-list', 'goals-patch', 'goals-update', 'profile-filter-links-delete', 'profile-filter-links-get', 'profile-filter-links-insert', 'profile-filter-links-list', 'profile-filter-links-patch', 'profile-filter-links-update', 'profile-user-links-delete', 'profile-user-links-insert', 'profile-user-links-list', 'profile-user-links-update', 'profiles-delete', 'profiles-get', 'profiles-insert', 'profiles-list', 'profiles-patch', 'profiles-update', 'segments-list', 'unsampled-reports-get', 'unsampled-reports-insert', 'unsampled-reports-list', 'uploads-delete-upload-data', 'uploads-get', 'uploads-list', 'uploads-upload-data', 'web-property-ad-words-links-delete', 'web-property-ad-words-links-get', 'web-property-ad-words-links-insert', 'web-property-ad-words-links-list', 'web-property-ad-words-links-patch', 'web-property-ad-words-links-update', 'webproperties-get', 'webproperties-insert', 'webproperties-list', 'webproperties-patch', 'webproperties-update', 'webproperty-user-links-delete', 'webproperty-user-links-insert', 'webproperty-user-links-list' and 'webproperty-user-links-update'", vec![ + ("account-summaries-list", + Some(r##"Lists account summaries (lightweight tree comprised of accounts/properties/profiles) to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_account-summaries-list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("account-user-links-delete", + Some(r##"Removes a user from the given account."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_account-user-links-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to delete the user link for."##), + Some(true), + Some(false)), + + (Some(r##"link-id"##), + None, + Some(r##"Link ID to delete the user link for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("account-user-links-insert", + Some(r##"Adds a new user to the given account."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_account-user-links-insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to create the user link for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("account-user-links-list", + Some(r##"Lists account-user links for a given account."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_account-user-links-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to retrieve the user links for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("account-user-links-update", + Some(r##"Updates permissions for an existing user on the given account."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_account-user-links-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to update the account-user link for."##), + Some(true), + Some(false)), + + (Some(r##"link-id"##), + None, + Some(r##"Link ID to update the account-user link for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("accounts-list", + Some(r##"Lists all accounts to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_accounts-list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("custom-data-sources-list", + Some(r##"List custom data sources to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_custom-data-sources-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account Id for the custom data sources to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property Id for the custom data sources to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("custom-dimensions-get", + Some(r##"Get a custom dimension to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_custom-dimensions-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID for the custom dimension to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID for the custom dimension to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"custom-dimension-id"##), + None, + Some(r##"The ID of the custom dimension to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("custom-dimensions-insert", + Some(r##"Create a new custom dimension."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_custom-dimensions-insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID for the custom dimension to create."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID for the custom dimension to create."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("custom-dimensions-list", + Some(r##"Lists custom dimensions to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_custom-dimensions-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID for the custom dimensions to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID for the custom dimensions to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("custom-dimensions-patch", + Some(r##"Updates an existing custom dimension. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_custom-dimensions-patch", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID for the custom dimension to update."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID for the custom dimension to update."##), + Some(true), + Some(false)), + + (Some(r##"custom-dimension-id"##), + None, + Some(r##"Custom dimension ID for the custom dimension to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("custom-dimensions-update", + Some(r##"Updates an existing custom dimension."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_custom-dimensions-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID for the custom dimension to update."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID for the custom dimension to update."##), + Some(true), + Some(false)), + + (Some(r##"custom-dimension-id"##), + None, + Some(r##"Custom dimension ID for the custom dimension to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("custom-metrics-get", + Some(r##"Get a custom metric to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_custom-metrics-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID for the custom metric to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID for the custom metric to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"custom-metric-id"##), + None, + Some(r##"The ID of the custom metric to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("custom-metrics-insert", + Some(r##"Create a new custom metric."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_custom-metrics-insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID for the custom metric to create."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID for the custom dimension to create."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("custom-metrics-list", + Some(r##"Lists custom metrics to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_custom-metrics-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID for the custom metrics to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID for the custom metrics to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("custom-metrics-patch", + Some(r##"Updates an existing custom metric. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_custom-metrics-patch", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID for the custom metric to update."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID for the custom metric to update."##), + Some(true), + Some(false)), + + (Some(r##"custom-metric-id"##), + None, + Some(r##"Custom metric ID for the custom metric to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("custom-metrics-update", + Some(r##"Updates an existing custom metric."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_custom-metrics-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID for the custom metric to update."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID for the custom metric to update."##), + Some(true), + Some(false)), + + (Some(r##"custom-metric-id"##), + None, + Some(r##"Custom metric ID for the custom metric to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("experiments-delete", + Some(r##"Delete an experiment."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_experiments-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to which the experiment belongs"##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to which the experiment belongs"##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to which the experiment belongs"##), + Some(true), + Some(false)), + + (Some(r##"experiment-id"##), + None, + Some(r##"ID of the experiment to delete"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("experiments-get", + Some(r##"Returns an experiment to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_experiments-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to retrieve the experiment for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to retrieve the experiment for."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to retrieve the experiment for."##), + Some(true), + Some(false)), + + (Some(r##"experiment-id"##), + None, + Some(r##"Experiment ID to retrieve the experiment for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("experiments-insert", + Some(r##"Create a new experiment."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_experiments-insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to create the experiment for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to create the experiment for."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to create the experiment for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("experiments-list", + Some(r##"Lists experiments to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_experiments-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to retrieve experiments for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to retrieve experiments for."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to retrieve experiments for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("experiments-patch", + Some(r##"Update an existing experiment. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_experiments-patch", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID of the experiment to update."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID of the experiment to update."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID of the experiment to update."##), + Some(true), + Some(false)), + + (Some(r##"experiment-id"##), + None, + Some(r##"Experiment ID of the experiment to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("experiments-update", + Some(r##"Update an existing experiment."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_experiments-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID of the experiment to update."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID of the experiment to update."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID of the experiment to update."##), + Some(true), + Some(false)), + + (Some(r##"experiment-id"##), + None, + Some(r##"Experiment ID of the experiment to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("filters-delete", + Some(r##"Delete a filter."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_filters-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to delete the filter for."##), + Some(true), + Some(false)), + + (Some(r##"filter-id"##), + None, + Some(r##"ID of the filter to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("filters-get", + Some(r##"Returns a filters to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_filters-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to retrieve filters for."##), + Some(true), + Some(false)), + + (Some(r##"filter-id"##), + None, + Some(r##"Filter ID to retrieve filters for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("filters-insert", + Some(r##"Create a new filter."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_filters-insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to create filter for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("filters-list", + Some(r##"Lists all filters for an account"##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_filters-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to retrieve filters for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("filters-patch", + Some(r##"Updates an existing filter. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_filters-patch", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to which the filter belongs."##), + Some(true), + Some(false)), + + (Some(r##"filter-id"##), + None, + Some(r##"ID of the filter to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("filters-update", + Some(r##"Updates an existing filter."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_filters-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to which the filter belongs."##), + Some(true), + Some(false)), + + (Some(r##"filter-id"##), + None, + Some(r##"ID of the filter to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("goals-get", + Some(r##"Gets a goal to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_goals-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to retrieve the goal for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to retrieve the goal for."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to retrieve the goal for."##), + Some(true), + Some(false)), + + (Some(r##"goal-id"##), + None, + Some(r##"Goal ID to retrieve the goal for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("goals-insert", + Some(r##"Create a new goal."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_goals-insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to create the goal for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to create the goal for."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to create the goal for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("goals-list", + Some(r##"Lists goals to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_goals-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to retrieve goals for. Can either be a specific account ID or '~all', which refers to all the accounts that user has access to."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to retrieve goals for. Can either be a specific web property ID or '~all', which refers to all the web properties that user has access to."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to retrieve goals for. Can either be a specific view (profile) ID or '~all', which refers to all the views (profiles) that user has access to."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("goals-patch", + Some(r##"Updates an existing view (profile). This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_goals-patch", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to update the goal."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to update the goal."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to update the goal."##), + Some(true), + Some(false)), + + (Some(r##"goal-id"##), + None, + Some(r##"Index of the goal to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("goals-update", + Some(r##"Updates an existing view (profile)."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_goals-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to update the goal."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to update the goal."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to update the goal."##), + Some(true), + Some(false)), + + (Some(r##"goal-id"##), + None, + Some(r##"Index of the goal to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("profile-filter-links-delete", + Some(r##"Delete a profile filter link."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profile-filter-links-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to which the profile filter link belongs."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property Id to which the profile filter link belongs."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"Profile ID to which the filter link belongs."##), + Some(true), + Some(false)), + + (Some(r##"link-id"##), + None, + Some(r##"ID of the profile filter link to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("profile-filter-links-get", + Some(r##"Returns a single profile filter link."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profile-filter-links-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to retrieve profile filter link for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property Id to retrieve profile filter link for."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"Profile ID to retrieve filter link for."##), + Some(true), + Some(false)), + + (Some(r##"link-id"##), + None, + Some(r##"ID of the profile filter link."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("profile-filter-links-insert", + Some(r##"Create a new profile filter link."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profile-filter-links-insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to create profile filter link for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property Id to create profile filter link for."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"Profile ID to create filter link for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("profile-filter-links-list", + Some(r##"Lists all profile filter links for a profile."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profile-filter-links-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to retrieve profile filter links for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property Id for profile filter links for. Can either be a specific web property ID or '~all', which refers to all the web properties that user has access to."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"Profile ID to retrieve filter links for. Can either be a specific profile ID or '~all', which refers to all the profiles that user has access to."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("profile-filter-links-patch", + Some(r##"Update an existing profile filter link. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profile-filter-links-patch", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to which profile filter link belongs."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property Id to which profile filter link belongs"##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"Profile ID to which filter link belongs"##), + Some(true), + Some(false)), + + (Some(r##"link-id"##), + None, + Some(r##"ID of the profile filter link to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("profile-filter-links-update", + Some(r##"Update an existing profile filter link."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profile-filter-links-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to which profile filter link belongs."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property Id to which profile filter link belongs"##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"Profile ID to which filter link belongs"##), + Some(true), + Some(false)), + + (Some(r##"link-id"##), + None, + Some(r##"ID of the profile filter link to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("profile-user-links-delete", + Some(r##"Removes a user from the given view (profile)."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profile-user-links-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to delete the user link for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web Property ID to delete the user link for."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to delete the user link for."##), + Some(true), + Some(false)), + + (Some(r##"link-id"##), + None, + Some(r##"Link ID to delete the user link for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("profile-user-links-insert", + Some(r##"Adds a new user to the given view (profile)."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profile-user-links-insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to create the user link for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web Property ID to create the user link for."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to create the user link for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("profile-user-links-list", + Some(r##"Lists profile-user links for a given view (profile)."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profile-user-links-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID which the given view (profile) belongs to."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web Property ID which the given view (profile) belongs to. Can either be a specific web property ID or '~all', which refers to all the web properties that user has access to."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to retrieve the profile-user links for. Can either be a specific profile ID or '~all', which refers to all the profiles that user has access to."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("profile-user-links-update", + Some(r##"Updates permissions for an existing user on the given view (profile)."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profile-user-links-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to update the user link for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web Property ID to update the user link for."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile ID) to update the user link for."##), + Some(true), + Some(false)), + + (Some(r##"link-id"##), + None, + Some(r##"Link ID to update the user link for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("profiles-delete", + Some(r##"Deletes a view (profile)."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profiles-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to delete the view (profile) for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to delete the view (profile) for."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"ID of the view (profile) to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("profiles-get", + Some(r##"Gets a view (profile) to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profiles-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to retrieve the goal for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to retrieve the goal for."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to retrieve the goal for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("profiles-insert", + Some(r##"Create a new view (profile)."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profiles-insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to create the view (profile) for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to create the view (profile) for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("profiles-list", + Some(r##"Lists views (profiles) to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profiles-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID for the view (profiles) to retrieve. Can either be a specific account ID or '~all', which refers to all the accounts to which the user has access."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID for the views (profiles) to retrieve. Can either be a specific web property ID or '~all', which refers to all the web properties to which the user has access."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("profiles-patch", + Some(r##"Updates an existing view (profile). This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profiles-patch", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to which the view (profile) belongs"##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to which the view (profile) belongs"##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"ID of the view (profile) to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("profiles-update", + Some(r##"Updates an existing view (profile)."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_profiles-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to which the view (profile) belongs"##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to which the view (profile) belongs"##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"ID of the view (profile) to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("segments-list", + Some(r##"Lists segments to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_segments-list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("unsampled-reports-get", + Some(r##"Returns a single unsampled report."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_unsampled-reports-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to retrieve unsampled report for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to retrieve unsampled reports for."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to retrieve unsampled report for."##), + Some(true), + Some(false)), + + (Some(r##"unsampled-report-id"##), + None, + Some(r##"ID of the unsampled report to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("unsampled-reports-insert", + Some(r##"Create a new unsampled report."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_unsampled-reports-insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to create the unsampled report for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to create the unsampled report for."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to create the unsampled report for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("unsampled-reports-list", + Some(r##"Lists unsampled reports to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_unsampled-reports-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to retrieve unsampled reports for. Must be a specific account ID, ~all is not supported."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to retrieve unsampled reports for. Must be a specific web property ID, ~all is not supported."##), + Some(true), + Some(false)), + + (Some(r##"profile-id"##), + None, + Some(r##"View (Profile) ID to retrieve unsampled reports for. Must be a specific view (profile) ID, ~all is not supported."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("uploads-delete-upload-data", + Some(r##"Delete data associated with a previous upload."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_uploads-delete-upload-data", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account Id for the uploads to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property Id for the uploads to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"custom-data-source-id"##), + None, + Some(r##"Custom data source Id for the uploads to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("uploads-get", + Some(r##"List uploads to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_uploads-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account Id for the upload to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property Id for the upload to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"custom-data-source-id"##), + None, + Some(r##"Custom data source Id for upload to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"upload-id"##), + None, + Some(r##"Upload Id to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("uploads-list", + Some(r##"List uploads to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_uploads-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account Id for the uploads to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property Id for the uploads to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"custom-data-source-id"##), + None, + Some(r##"Custom data source Id for uploads to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("uploads-upload-data", + Some(r##"Upload data for a custom data source."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_uploads-upload-data", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account Id associated with the upload."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property UA-string associated with the upload."##), + Some(true), + Some(false)), + + (Some(r##"custom-data-source-id"##), + None, + Some(r##"Custom data source Id to which the data being uploaded belongs."##), + Some(true), + Some(false)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("web-property-ad-words-links-delete", + Some(r##"Deletes a web property-AdWords link."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_web-property-ad-words-links-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"ID of the account which the given web property belongs to."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to delete the AdWords link for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-ad-words-link-id"##), + None, + Some(r##"Web property AdWords link ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("web-property-ad-words-links-get", + Some(r##"Returns a web property-AdWords link to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_web-property-ad-words-links-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"ID of the account which the given web property belongs to."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to retrieve the AdWords link for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-ad-words-link-id"##), + None, + Some(r##"Web property-AdWords link ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("web-property-ad-words-links-insert", + Some(r##"Creates a webProperty-AdWords link."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_web-property-ad-words-links-insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"ID of the Google Analytics account to create the link for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to create the link for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("web-property-ad-words-links-list", + Some(r##"Lists webProperty-AdWords links for a given web property."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_web-property-ad-words-links-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"ID of the account which the given web property belongs to."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to retrieve the AdWords links for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("web-property-ad-words-links-patch", + Some(r##"Updates an existing webProperty-AdWords link. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_web-property-ad-words-links-patch", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"ID of the account which the given web property belongs to."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to retrieve the AdWords link for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-ad-words-link-id"##), + None, + Some(r##"Web property-AdWords link ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("web-property-ad-words-links-update", + Some(r##"Updates an existing webProperty-AdWords link."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_web-property-ad-words-links-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"ID of the account which the given web property belongs to."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to retrieve the AdWords link for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-ad-words-link-id"##), + None, + Some(r##"Web property-AdWords link ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("webproperties-get", + Some(r##"Gets a web property to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_webproperties-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to retrieve the web property for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"ID to retrieve the web property for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("webproperties-insert", + Some(r##"Create a new property if the account has fewer than 20 properties. Web properties are visible in the Google Analytics interface only if they have at least one profile."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_webproperties-insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to create the web property for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("webproperties-list", + Some(r##"Lists web properties to which the user has access."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_webproperties-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to retrieve web properties for. Can either be a specific account ID or '~all', which refers to all the accounts that user has access to."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("webproperties-patch", + Some(r##"Updates an existing web property. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_webproperties-patch", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to which the web property belongs"##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("webproperties-update", + Some(r##"Updates an existing web property."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_webproperties-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to which the web property belongs"##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("webproperty-user-links-delete", + Some(r##"Removes a user from the given web property."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_webproperty-user-links-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to delete the user link for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web Property ID to delete the user link for."##), + Some(true), + Some(false)), + + (Some(r##"link-id"##), + None, + Some(r##"Link ID to delete the user link for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("webproperty-user-links-insert", + Some(r##"Adds a new user to the given web property."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_webproperty-user-links-insert", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to create the user link for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web Property ID to create the user link for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("webproperty-user-links-list", + Some(r##"Lists webProperty-user links for a given web property."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_webproperty-user-links-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID which the given web property belongs to."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web Property ID for the webProperty-user links to retrieve. Can either be a specific web property ID or '~all', which refers to all the web properties that user has access to."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("webproperty-user-links-update", + Some(r##"Updates permissions for an existing user on the given web property."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/management_webproperty-user-links-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"Account ID to update the account-user link for."##), + Some(true), + Some(false)), + + (Some(r##"web-property-id"##), + None, + Some(r##"Web property ID to update the account-user link for."##), + Some(true), + Some(false)), + + (Some(r##"link-id"##), + None, + Some(r##"Link ID to update the account-user link for."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("metadata", "methods: 'columns-list'", vec![ + ("columns-list", + Some(r##"Lists all columns for a report type"##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/metadata_columns-list", + vec![ + (Some(r##"report-type"##), + None, + Some(r##"Report type. Allowed Values: 'ga'. Where 'ga' corresponds to the Core Reporting API"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("provisioning", "methods: 'create-account-ticket'", vec![ + ("create-account-ticket", + Some(r##"Creates an account ticket."##), + "Details at http://byron.github.io/google-apis-rs/google_analytics3_cli/provisioning_create-account-ticket", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("analytics3") + .author("Sebastian Thiel ") + .version("0.2.0+20150305") + .about("View and manage your Google Analytics data") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_analytics3_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + if arg_name_str == "mode" { + arg = arg.number_of_values(2); + arg = arg.value_names(&upload_value_names); + + scmd = scmd.arg(Arg::with_name("mime") + .short("m") + .requires("mode") + .required(false) + .help("The file's mime time, like 'application/octet-stream'") + .takes_value(true)); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/analytics3/Cargo.toml b/gen/analytics3/Cargo.toml index f871077765..66ddd66355 100644 --- a/gen/analytics3/Cargo.toml +++ b/gen/analytics3/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-analytics3" -version = "0.1.6+20150305" +version = "0.1.7+20150305" authors = ["Sebastian Thiel "] description = "A complete library to interact with analytics (protocol v3)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/analytics3" @@ -15,9 +15,10 @@ keywords = ["analytics", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/analytics3/README.md b/gen/analytics3/README.md index 663029404c..e5a3e260a5 100644 --- a/gen/analytics3/README.md +++ b/gen/analytics3/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-analytics3` library allows access to all features of the *Google analytics* service. -This documentation was generated from *analytics* crate version *0.1.6+20150305*, where *20150305* is the exact revision of the *analytics:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *analytics* crate version *0.1.7+20150305*, where *20150305* is the exact revision of the *analytics:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *analytics* *v3* API can be found at the [official documentation site](https://developers.google.com/analytics/). @@ -178,7 +178,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_analytics3/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_analytics3/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/analytics3/src/cmn.rs b/gen/analytics3/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/analytics3/src/cmn.rs +++ b/gen/analytics3/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/analytics3/src/lib.rs b/gen/analytics3/src/lib.rs index 614969a678..0e797a5f89 100644 --- a/gen/analytics3/src/lib.rs +++ b/gen/analytics3/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *analytics* crate version *0.1.6+20150305*, where *20150305* is the exact revision of the *analytics:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *analytics* crate version *0.1.7+20150305*, where *20150305* is the exact revision of the *analytics:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *analytics* *v3* API can be found at the //! [official documentation site](https://developers.google.com/analytics/). @@ -179,7 +179,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -188,7 +188,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -204,6 +203,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -346,7 +346,7 @@ impl<'a, C, A> Analytics Analytics { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -364,7 +364,7 @@ impl<'a, C, A> Analytics } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -5162,6 +5162,7 @@ impl<'a, C, A> ManagementWebpropertyInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Webproperty)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5217,11 +5218,20 @@ impl<'a, C, A> ManagementWebpropertyInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5244,7 +5254,7 @@ impl<'a, C, A> ManagementWebpropertyInsertCall<'a, C, A> where C: BorrowMut ManagementProfileGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5499,7 +5509,7 @@ impl<'a, C, A> ManagementProfileGetCall<'a, C, A> where C: BorrowMut ManagementAccountListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5742,7 +5752,7 @@ impl<'a, C, A> ManagementAccountListCall<'a, C, A> where C: BorrowMut ManagementProfileFilterLinkPatchCall<'a, C, A> where C: BorrowMut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ProfileFilterLink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5976,11 +5987,20 @@ impl<'a, C, A> ManagementProfileFilterLinkPatchCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6003,7 +6023,7 @@ impl<'a, C, A> ManagementProfileFilterLinkPatchCall<'a, C, A> where C: BorrowMut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6265,7 +6285,7 @@ impl<'a, C, A> ManagementWebpropertyUserLinkDeleteCall<'a, C, A> where C: Borrow if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6287,7 +6307,7 @@ impl<'a, C, A> ManagementWebpropertyUserLinkDeleteCall<'a, C, A> where C: Borrow access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6519,7 +6539,7 @@ impl<'a, C, A> ManagementProfileUserLinkDeleteCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6541,7 +6561,7 @@ impl<'a, C, A> ManagementProfileUserLinkDeleteCall<'a, C, A> where C: BorrowMut< access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6733,6 +6753,7 @@ impl<'a, C, A> ManagementProfileUserLinkUpdateCall<'a, C, A> where C: BorrowMut< /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, EntityUserLink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6791,11 +6812,20 @@ impl<'a, C, A> ManagementProfileUserLinkUpdateCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6818,7 +6848,7 @@ impl<'a, C, A> ManagementProfileUserLinkUpdateCall<'a, C, A> where C: BorrowMut< request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7029,6 +7059,7 @@ impl<'a, C, A> ManagementFilterInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Filter)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7084,11 +7115,20 @@ impl<'a, C, A> ManagementFilterInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7111,7 +7151,7 @@ impl<'a, C, A> ManagementFilterInsertCall<'a, C, A> where C: BorrowMut ManagementAccountUserLinkUpdateCall<'a, C, A> where C: BorrowMut< /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, EntityUserLink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7349,11 +7390,20 @@ impl<'a, C, A> ManagementAccountUserLinkUpdateCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7376,7 +7426,7 @@ impl<'a, C, A> ManagementAccountUserLinkUpdateCall<'a, C, A> where C: BorrowMut< request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7568,6 +7618,7 @@ impl<'a, C, A> ManagementWebpropertyUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Webproperty)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7624,11 +7675,20 @@ impl<'a, C, A> ManagementWebpropertyUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7651,7 +7711,7 @@ impl<'a, C, A> ManagementWebpropertyUpdateCall<'a, C, A> where C: BorrowMut ManagementWebpropertyUserLinkUpdateCall<'a, C, A> where C: Borrow /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, EntityUserLink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7901,11 +7962,20 @@ impl<'a, C, A> ManagementWebpropertyUserLinkUpdateCall<'a, C, A> where C: Borrow if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7928,7 +7998,7 @@ impl<'a, C, A> ManagementWebpropertyUserLinkUpdateCall<'a, C, A> where C: Borrow request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8131,6 +8201,7 @@ impl<'a, C, A> ManagementUnsampledReportInsertCall<'a, C, A> where C: BorrowMut< /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, UnsampledReport)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8188,11 +8259,20 @@ impl<'a, C, A> ManagementUnsampledReportInsertCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8215,7 +8295,7 @@ impl<'a, C, A> ManagementUnsampledReportInsertCall<'a, C, A> where C: BorrowMut< request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8468,7 +8548,7 @@ impl<'a, C, A> ManagementCustomMetricGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8490,7 +8570,7 @@ impl<'a, C, A> ManagementCustomMetricGetCall<'a, C, A> where C: BorrowMut ManagementUploadGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8755,7 +8835,7 @@ impl<'a, C, A> ManagementUploadGetCall<'a, C, A> where C: BorrowMut ManagementWebPropertyAdWordsLinkGetCall<'a, C, A> where C: Borrow if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9028,7 +9108,7 @@ impl<'a, C, A> ManagementWebPropertyAdWordsLinkGetCall<'a, C, A> where C: Borrow access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9277,7 +9357,7 @@ impl<'a, C, A> ManagementWebpropertyUserLinkListCall<'a, C, A> where C: BorrowMu if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9299,7 +9379,7 @@ impl<'a, C, A> ManagementWebpropertyUserLinkListCall<'a, C, A> where C: BorrowMu access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9495,6 +9575,7 @@ impl<'a, C, A> ManagementProfileFilterLinkUpdateCall<'a, C, A> where C: BorrowMu /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ProfileFilterLink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9553,11 +9634,20 @@ impl<'a, C, A> ManagementProfileFilterLinkUpdateCall<'a, C, A> where C: BorrowMu if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9580,7 +9670,7 @@ impl<'a, C, A> ManagementProfileFilterLinkUpdateCall<'a, C, A> where C: BorrowMu request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9845,7 +9935,7 @@ impl<'a, C, A> ManagementExperimentGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9867,7 +9957,7 @@ impl<'a, C, A> ManagementExperimentGetCall<'a, C, A> where C: BorrowMut ManagementCustomDimensionUpdateCall<'a, C, A> where C: BorrowMut< /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CustomDimension)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10130,11 +10221,20 @@ impl<'a, C, A> ManagementCustomDimensionUpdateCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10157,7 +10257,7 @@ impl<'a, C, A> ManagementCustomDimensionUpdateCall<'a, C, A> where C: BorrowMut< request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -10419,7 +10519,7 @@ impl<'a, C, A> ManagementUnsampledReportGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10441,7 +10541,7 @@ impl<'a, C, A> ManagementUnsampledReportGetCall<'a, C, A> where C: BorrowMut ManagementProfileFilterLinkInsertCall<'a, C, A> where C: BorrowMu /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ProfileFilterLink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10699,11 +10800,20 @@ impl<'a, C, A> ManagementProfileFilterLinkInsertCall<'a, C, A> where C: BorrowMu if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10726,7 +10836,7 @@ impl<'a, C, A> ManagementProfileFilterLinkInsertCall<'a, C, A> where C: BorrowMu request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -10928,6 +11038,7 @@ impl<'a, C, A> ManagementFilterUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Filter)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10984,11 +11095,20 @@ impl<'a, C, A> ManagementFilterUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11011,7 +11131,7 @@ impl<'a, C, A> ManagementFilterUpdateCall<'a, C, A> where C: BorrowMut ManagementProfileFilterLinkDeleteCall<'a, C, A> where C: BorrowMu if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11277,7 +11397,7 @@ impl<'a, C, A> ManagementProfileFilterLinkDeleteCall<'a, C, A> where C: BorrowMu access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11498,7 +11618,7 @@ impl<'a, C, A> ManagementSegmentListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11520,7 +11640,7 @@ impl<'a, C, A> ManagementSegmentListCall<'a, C, A> where C: BorrowMut ManagementProfileDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11766,7 +11886,7 @@ impl<'a, C, A> ManagementProfileDeleteCall<'a, C, A> where C: BorrowMut ManagementGoalPatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Goal)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12006,11 +12127,20 @@ impl<'a, C, A> ManagementGoalPatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12033,7 +12163,7 @@ impl<'a, C, A> ManagementGoalPatchCall<'a, C, A> where C: BorrowMut ManagementCustomDimensionPatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, CustomDimension)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12308,11 +12439,20 @@ impl<'a, C, A> ManagementCustomDimensionPatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12335,7 +12475,7 @@ impl<'a, C, A> ManagementCustomDimensionPatchCall<'a, C, A> where C: BorrowMut ManagementExperimentPatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Experiment)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12604,11 +12745,20 @@ impl<'a, C, A> ManagementExperimentPatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12631,7 +12781,7 @@ impl<'a, C, A> ManagementExperimentPatchCall<'a, C, A> where C: BorrowMut ManagementExperimentListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12926,7 +13076,7 @@ impl<'a, C, A> ManagementExperimentListCall<'a, C, A> where C: BorrowMut ManagementProfileListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13211,7 +13361,7 @@ impl<'a, C, A> ManagementProfileListCall<'a, C, A> where C: BorrowMut ManagementGoalListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13488,7 +13638,7 @@ impl<'a, C, A> ManagementGoalListCall<'a, C, A> where C: BorrowMut ManagementGoalInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Goal)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13750,11 +13901,20 @@ impl<'a, C, A> ManagementGoalInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13777,7 +13937,7 @@ impl<'a, C, A> ManagementGoalInsertCall<'a, C, A> where C: BorrowMut ManagementCustomMetricPatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, CustomMetric)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14042,11 +14203,20 @@ impl<'a, C, A> ManagementCustomMetricPatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14069,7 +14239,7 @@ impl<'a, C, A> ManagementCustomMetricPatchCall<'a, C, A> where C: BorrowMut ManagementUploadUploadDataCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14377,7 +14547,7 @@ impl<'a, C, A> ManagementUploadUploadDataCall<'a, C, A> where C: BorrowMut ManagementUploadUploadDataCall<'a, C, A> where C: BorrowMut().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -14463,6 +14633,7 @@ impl<'a, C, A> ManagementUploadUploadDataCall<'a, C, A> where C: BorrowMut { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -14651,6 +14822,7 @@ impl<'a, C, A> ManagementAccountUserLinkInsertCall<'a, C, A> where C: BorrowMut< /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, EntityUserLink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14706,11 +14878,20 @@ impl<'a, C, A> ManagementAccountUserLinkInsertCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14733,7 +14914,7 @@ impl<'a, C, A> ManagementAccountUserLinkInsertCall<'a, C, A> where C: BorrowMut< request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -14915,6 +15096,7 @@ impl<'a, C, A> ManagementWebpropertyUserLinkInsertCall<'a, C, A> where C: Borrow /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, EntityUserLink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14971,11 +15153,20 @@ impl<'a, C, A> ManagementWebpropertyUserLinkInsertCall<'a, C, A> where C: Borrow if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14998,7 +15189,7 @@ impl<'a, C, A> ManagementWebpropertyUserLinkInsertCall<'a, C, A> where C: Borrow request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -15242,7 +15433,7 @@ impl<'a, C, A> ManagementExperimentDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15264,7 +15455,7 @@ impl<'a, C, A> ManagementExperimentDeleteCall<'a, C, A> where C: BorrowMut ManagementProfilePatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Profile)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15512,11 +15704,20 @@ impl<'a, C, A> ManagementProfilePatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15539,7 +15740,7 @@ impl<'a, C, A> ManagementProfilePatchCall<'a, C, A> where C: BorrowMut ManagementFilterGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15812,7 +16013,7 @@ impl<'a, C, A> ManagementFilterGetCall<'a, C, A> where C: BorrowMut ManagementWebPropertyAdWordsLinkListCall<'a, C, A> where C: Borro if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16073,7 +16274,7 @@ impl<'a, C, A> ManagementWebPropertyAdWordsLinkListCall<'a, C, A> where C: Borro access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -16298,7 +16499,7 @@ impl<'a, C, A> ManagementAccountSummaryListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16320,7 +16521,7 @@ impl<'a, C, A> ManagementAccountSummaryListCall<'a, C, A> where C: BorrowMut ManagementCustomDimensionListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16575,7 +16776,7 @@ impl<'a, C, A> ManagementCustomDimensionListCall<'a, C, A> where C: BorrowMut ManagementUploadListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16852,7 +17053,7 @@ impl<'a, C, A> ManagementUploadListCall<'a, C, A> where C: BorrowMut ManagementProfileUserLinkListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17139,7 +17340,7 @@ impl<'a, C, A> ManagementProfileUserLinkListCall<'a, C, A> where C: BorrowMut ManagementAccountUserLinkListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17422,7 +17623,7 @@ impl<'a, C, A> ManagementAccountUserLinkListCall<'a, C, A> where C: BorrowMut ManagementCustomMetricUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, CustomMetric)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17669,11 +17871,20 @@ impl<'a, C, A> ManagementCustomMetricUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17696,7 +17907,7 @@ impl<'a, C, A> ManagementCustomMetricUpdateCall<'a, C, A> where C: BorrowMut ManagementUploadDeleteUploadDataCall<'a, C, A> where C: BorrowMut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17962,11 +18174,20 @@ impl<'a, C, A> ManagementUploadDeleteUploadDataCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17989,7 +18210,7 @@ impl<'a, C, A> ManagementUploadDeleteUploadDataCall<'a, C, A> where C: BorrowMut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -18183,6 +18404,7 @@ impl<'a, C, A> ManagementExperimentUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Experiment)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -18241,11 +18463,20 @@ impl<'a, C, A> ManagementExperimentUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -18268,7 +18499,7 @@ impl<'a, C, A> ManagementExperimentUpdateCall<'a, C, A> where C: BorrowMut ManagementGoalUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Goal)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -18540,11 +18772,20 @@ impl<'a, C, A> ManagementGoalUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -18567,7 +18808,7 @@ impl<'a, C, A> ManagementGoalUpdateCall<'a, C, A> where C: BorrowMut ManagementCustomDataSourceListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18860,7 +19101,7 @@ impl<'a, C, A> ManagementCustomDataSourceListCall<'a, C, A> where C: BorrowMut ManagementCustomMetricListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19135,7 +19376,7 @@ impl<'a, C, A> ManagementCustomMetricListCall<'a, C, A> where C: BorrowMut ManagementUnsampledReportListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19412,7 +19653,7 @@ impl<'a, C, A> ManagementUnsampledReportListCall<'a, C, A> where C: BorrowMut ManagementWebpropertyGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19687,7 +19928,7 @@ impl<'a, C, A> ManagementWebpropertyGetCall<'a, C, A> where C: BorrowMut ManagementExperimentInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Experiment)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -19925,11 +20167,20 @@ impl<'a, C, A> ManagementExperimentInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -19952,7 +20203,7 @@ impl<'a, C, A> ManagementExperimentInsertCall<'a, C, A> where C: BorrowMut ManagementCustomDimensionGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -20227,7 +20478,7 @@ impl<'a, C, A> ManagementCustomDimensionGetCall<'a, C, A> where C: BorrowMut ManagementProfileFilterLinkListCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -20500,7 +20751,7 @@ impl<'a, C, A> ManagementProfileFilterLinkListCall<'a, C, A> where C: BorrowMut< access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -20704,6 +20955,7 @@ impl<'a, C, A> ManagementWebpropertyPatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Webproperty)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -20760,11 +21012,20 @@ impl<'a, C, A> ManagementWebpropertyPatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -20787,7 +21048,7 @@ impl<'a, C, A> ManagementWebpropertyPatchCall<'a, C, A> where C: BorrowMut ManagementCustomDimensionInsertCall<'a, C, A> where C: BorrowMut< /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CustomDimension)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -21035,11 +21297,20 @@ impl<'a, C, A> ManagementCustomDimensionInsertCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -21062,7 +21333,7 @@ impl<'a, C, A> ManagementCustomDimensionInsertCall<'a, C, A> where C: BorrowMut< request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -21254,6 +21525,7 @@ impl<'a, C, A> ManagementCustomMetricInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, CustomMetric)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -21310,11 +21582,20 @@ impl<'a, C, A> ManagementCustomMetricInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -21337,7 +21618,7 @@ impl<'a, C, A> ManagementCustomMetricInsertCall<'a, C, A> where C: BorrowMut ManagementProfileUserLinkInsertCall<'a, C, A> where C: BorrowMut< /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, EntityUserLink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -21587,11 +21869,20 @@ impl<'a, C, A> ManagementProfileUserLinkInsertCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -21614,7 +21905,7 @@ impl<'a, C, A> ManagementProfileUserLinkInsertCall<'a, C, A> where C: BorrowMut< request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -21873,7 +22164,7 @@ impl<'a, C, A> ManagementWebpropertyListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -21895,7 +22186,7 @@ impl<'a, C, A> ManagementWebpropertyListCall<'a, C, A> where C: BorrowMut ManagementWebPropertyAdWordsLinkInsertCall<'a, C, A> where C: Bor /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, EntityAdWordsLink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -22135,11 +22427,20 @@ impl<'a, C, A> ManagementWebPropertyAdWordsLinkInsertCall<'a, C, A> where C: Bor if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -22162,7 +22463,7 @@ impl<'a, C, A> ManagementWebPropertyAdWordsLinkInsertCall<'a, C, A> where C: Bor request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -22355,6 +22656,7 @@ impl<'a, C, A> ManagementWebPropertyAdWordsLinkPatchCall<'a, C, A> where C: Borr /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, EntityAdWordsLink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -22412,11 +22714,20 @@ impl<'a, C, A> ManagementWebPropertyAdWordsLinkPatchCall<'a, C, A> where C: Borr if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -22439,7 +22750,7 @@ impl<'a, C, A> ManagementWebPropertyAdWordsLinkPatchCall<'a, C, A> where C: Borr request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -22694,7 +23005,7 @@ impl<'a, C, A> ManagementGoalGetCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -22716,7 +23027,7 @@ impl<'a, C, A> ManagementGoalGetCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -22966,7 +23277,7 @@ impl<'a, C, A> ManagementWebPropertyAdWordsLinkDeleteCall<'a, C, A> where C: Bor if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -22988,7 +23299,7 @@ impl<'a, C, A> ManagementWebPropertyAdWordsLinkDeleteCall<'a, C, A> where C: Bor access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -23169,6 +23480,7 @@ impl<'a, C, A> ManagementWebPropertyAdWordsLinkUpdateCall<'a, C, A> where C: Bor /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, EntityAdWordsLink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -23226,11 +23538,20 @@ impl<'a, C, A> ManagementWebPropertyAdWordsLinkUpdateCall<'a, C, A> where C: Bor if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -23253,7 +23574,7 @@ impl<'a, C, A> ManagementWebPropertyAdWordsLinkUpdateCall<'a, C, A> where C: Bor request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -23455,6 +23776,7 @@ impl<'a, C, A> ManagementFilterPatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Filter)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -23511,11 +23833,20 @@ impl<'a, C, A> ManagementFilterPatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -23538,7 +23869,7 @@ impl<'a, C, A> ManagementFilterPatchCall<'a, C, A> where C: BorrowMut ManagementFilterListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -23809,7 +24140,7 @@ impl<'a, C, A> ManagementFilterListCall<'a, C, A> where C: BorrowMut ManagementFilterDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -24064,7 +24395,7 @@ impl<'a, C, A> ManagementFilterDeleteCall<'a, C, A> where C: BorrowMut ManagementProfileInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Profile)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -24300,11 +24632,20 @@ impl<'a, C, A> ManagementProfileInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -24327,7 +24668,7 @@ impl<'a, C, A> ManagementProfileInsertCall<'a, C, A> where C: BorrowMut ManagementAccountUserLinkDeleteCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -24589,7 +24930,7 @@ impl<'a, C, A> ManagementAccountUserLinkDeleteCall<'a, C, A> where C: BorrowMut< access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -24760,6 +25101,7 @@ impl<'a, C, A> ManagementProfileUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Profile)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -24817,11 +25159,20 @@ impl<'a, C, A> ManagementProfileUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -24844,7 +25195,7 @@ impl<'a, C, A> ManagementProfileUpdateCall<'a, C, A> where C: BorrowMut ManagementProfileFilterLinkGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -25121,7 +25472,7 @@ impl<'a, C, A> ManagementProfileFilterLinkGetCall<'a, C, A> where C: BorrowMut DataMcfGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -25402,7 +25753,7 @@ impl<'a, C, A> DataMcfGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -25713,7 +26064,7 @@ impl<'a, C, A> DataGaGetCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -25735,7 +26086,7 @@ impl<'a, C, A> DataGaGetCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -26036,7 +26387,7 @@ impl<'a, C, A> DataRealtimeGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -26058,7 +26409,7 @@ impl<'a, C, A> DataRealtimeGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -26264,6 +26615,7 @@ impl<'a, C, A> ProvisioningCreateAccountTicketCall<'a, C, A> where C: BorrowMut< /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AccountTicket)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -26294,11 +26646,20 @@ impl<'a, C, A> ProvisioningCreateAccountTicketCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -26321,7 +26682,7 @@ impl<'a, C, A> ProvisioningCreateAccountTicketCall<'a, C, A> where C: BorrowMut< request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -26540,7 +26901,7 @@ impl<'a, C, A> MetadataColumnListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -26562,7 +26923,7 @@ impl<'a, C, A> MetadataColumnListCall<'a, C, A> where C: BorrowMut"] description = "A complete library to interact with Android Enterprise (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/androidenterprise1-cli" @@ -16,15 +16,14 @@ keywords = ["androidenterprise", "google", "cli"] name = "androidenterprise1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-androidenterprise1] path = "../androidenterprise1" diff --git a/gen/androidenterprise1-cli/README.md b/gen/androidenterprise1-cli/README.md index bde6ec1c48..a3f8367fd5 100644 --- a/gen/androidenterprise1-cli/README.md +++ b/gen/androidenterprise1-cli/README.md @@ -12,62 +12,71 @@ If data-structures are requested, these will be returned as pretty-printed JSON, # Usage -This documentation was generated from the *Android Enterprise* API at revision *20150309*. The CLI is at version *0.1.0*. +This documentation was generated from the *Android Enterprise* API at revision *20150309*. The CLI is at version *0.2.0*. ```bash - androidenterprise1 [options] collections delete [-p ...] - androidenterprise1 [options] collections get [-p ...] [-o ] - androidenterprise1 [options] collections insert -r ... [-p ...] [-o ] - androidenterprise1 [options] collections list [-p ...] [-o ] - androidenterprise1 [options] collections patch -r ... [-p ...] [-o ] - androidenterprise1 [options] collections update -r ... [-p ...] [-o ] - androidenterprise1 [options] collectionviewers delete [-p ...] - androidenterprise1 [options] collectionviewers get [-p ...] [-o ] - androidenterprise1 [options] collectionviewers list [-p ...] [-o ] - androidenterprise1 [options] collectionviewers patch -r ... [-p ...] [-o ] - androidenterprise1 [options] collectionviewers update -r ... [-p ...] [-o ] - androidenterprise1 [options] devices get [-p ...] [-o ] - androidenterprise1 [options] devices get-state [-p ...] [-o ] - androidenterprise1 [options] devices list [-p ...] [-o ] - androidenterprise1 [options] devices set-state -r ... [-p ...] [-o ] - androidenterprise1 [options] enterprises delete [-p ...] - androidenterprise1 [options] enterprises enroll -r ... [-p ...] [-o ] - androidenterprise1 [options] enterprises get [-p ...] [-o ] - androidenterprise1 [options] enterprises insert -r ... [-p ...] [-o ] - androidenterprise1 [options] enterprises list [-p ...] [-o ] - androidenterprise1 [options] enterprises set-account -r ... [-p ...] [-o ] - androidenterprise1 [options] enterprises unenroll [-p ...] - androidenterprise1 [options] entitlements delete [-p ...] - androidenterprise1 [options] entitlements get [-p ...] [-o ] - androidenterprise1 [options] entitlements list [-p ...] [-o ] - androidenterprise1 [options] entitlements patch -r ... [-p ...] [-o ] - androidenterprise1 [options] entitlements update -r ... [-p ...] [-o ] - androidenterprise1 [options] grouplicenses get [-p ...] [-o ] - androidenterprise1 [options] grouplicenses list [-p ...] [-o ] - androidenterprise1 [options] grouplicenseusers list [-p ...] [-o ] - androidenterprise1 [options] installs delete [-p ...] - androidenterprise1 [options] installs get [-p ...] [-o ] - androidenterprise1 [options] installs list [-p ...] [-o ] - androidenterprise1 [options] installs patch -r ... [-p ...] [-o ] - androidenterprise1 [options] installs update -r ... [-p ...] [-o ] - androidenterprise1 [options] permissions get [-p ...] [-o ] - androidenterprise1 [options] products get [-p ...] [-o ] - androidenterprise1 [options] products get-app-restrictions-schema [-p ...] [-o ] - androidenterprise1 [options] products get-permissions [-p ...] [-o ] - androidenterprise1 [options] products update-permissions -r ... [-p ...] [-o ] - androidenterprise1 [options] users generate-token [-p ...] [-o ] - androidenterprise1 [options] users get [-p ...] [-o ] - androidenterprise1 [options] users list [-p ...] [-o ] - androidenterprise1 [options] users revoke-token [-p ...] +androidenterprise1 [options] + collections + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + collectionviewers + delete [-p ]... + get [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + devices + get [-p ]... [-o ] + get-state [-p ]... [-o ] + list [-p ]... [-o ] + set-state (-r )... [-p ]... [-o ] + enterprises + delete [-p ]... + enroll (-r )... [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + set-account (-r )... [-p ]... [-o ] + unenroll [-p ]... + entitlements + delete [-p ]... + get [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + grouplicenses + get [-p ]... [-o ] + list [-p ]... [-o ] + grouplicenseusers + list [-p ]... [-o ] + installs + delete [-p ]... + get [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + permissions + get [-p ]... [-o ] + products + get [-p ]... [-o ] + get-app-restrictions-schema [-p ]... [-o ] + get-permissions [-p ]... [-o ] + update-permissions (-r )... [-p ]... [-o ] + users + generate-token [-p ]... [-o ] + get [-p ]... [-o ] + list [-p ]... [-o ] + revoke-token [-p ]... androidenterprise1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/androidenterprise1-cli/mkdocs.yml b/gen/androidenterprise1-cli/mkdocs.yml index b15d33ea88..0862b7435d 100644 --- a/gen/androidenterprise1-cli/mkdocs.yml +++ b/gen/androidenterprise1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Android Enterprise v0.1.0+20150309 +site_name: Android Enterprise v0.2.0+20150309 site_url: http://byron.github.io/google-apis-rs/google-androidenterprise1-cli site_description: Write integrating applications with bcore diff --git a/gen/androidenterprise1-cli/src/cmn.rs b/gen/androidenterprise1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/androidenterprise1-cli/src/cmn.rs +++ b/gen/androidenterprise1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/androidenterprise1-cli/src/main.rs b/gen/androidenterprise1-cli/src/main.rs index e80ace2496..f12cb492a0 100644 --- a/gen/androidenterprise1-cli/src/main.rs +++ b/gen/androidenterprise1-cli/src/main.rs @@ -2,202 +2,148 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_androidenterprise1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - androidenterprise1 [options] collections delete [-p ...] - androidenterprise1 [options] collections get [-p ...] [-o ] - androidenterprise1 [options] collections insert -r ... [-p ...] [-o ] - androidenterprise1 [options] collections list [-p ...] [-o ] - androidenterprise1 [options] collections patch -r ... [-p ...] [-o ] - androidenterprise1 [options] collections update -r ... [-p ...] [-o ] - androidenterprise1 [options] collectionviewers delete [-p ...] - androidenterprise1 [options] collectionviewers get [-p ...] [-o ] - androidenterprise1 [options] collectionviewers list [-p ...] [-o ] - androidenterprise1 [options] collectionviewers patch -r ... [-p ...] [-o ] - androidenterprise1 [options] collectionviewers update -r ... [-p ...] [-o ] - androidenterprise1 [options] devices get [-p ...] [-o ] - androidenterprise1 [options] devices get-state [-p ...] [-o ] - androidenterprise1 [options] devices list [-p ...] [-o ] - androidenterprise1 [options] devices set-state -r ... [-p ...] [-o ] - androidenterprise1 [options] enterprises delete [-p ...] - androidenterprise1 [options] enterprises enroll -r ... [-p ...] [-o ] - androidenterprise1 [options] enterprises get [-p ...] [-o ] - androidenterprise1 [options] enterprises insert -r ... [-p ...] [-o ] - androidenterprise1 [options] enterprises list [-p ...] [-o ] - androidenterprise1 [options] enterprises set-account -r ... [-p ...] [-o ] - androidenterprise1 [options] enterprises unenroll [-p ...] - androidenterprise1 [options] entitlements delete [-p ...] - androidenterprise1 [options] entitlements get [-p ...] [-o ] - androidenterprise1 [options] entitlements list [-p ...] [-o ] - androidenterprise1 [options] entitlements patch -r ... [-p ...] [-o ] - androidenterprise1 [options] entitlements update -r ... [-p ...] [-o ] - androidenterprise1 [options] grouplicenses get [-p ...] [-o ] - androidenterprise1 [options] grouplicenses list [-p ...] [-o ] - androidenterprise1 [options] grouplicenseusers list [-p ...] [-o ] - androidenterprise1 [options] installs delete [-p ...] - androidenterprise1 [options] installs get [-p ...] [-o ] - androidenterprise1 [options] installs list [-p ...] [-o ] - androidenterprise1 [options] installs patch -r ... [-p ...] [-o ] - androidenterprise1 [options] installs update -r ... [-p ...] [-o ] - androidenterprise1 [options] permissions get [-p ...] [-o ] - androidenterprise1 [options] products get [-p ...] [-o ] - androidenterprise1 [options] products get-app-restrictions-schema [-p ...] [-o ] - androidenterprise1 [options] products get-permissions [-p ...] [-o ] - androidenterprise1 [options] products update-permissions -r ... [-p ...] [-o ] - androidenterprise1 [options] users generate-token [-p ...] [-o ] - androidenterprise1 [options] users get [-p ...] [-o ] - androidenterprise1 [options] users list [-p ...] [-o ] - androidenterprise1 [options] users revoke-token [-p ...] - androidenterprise1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::AndroidEnterprise>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _collections_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.collections().delete(&self.opt.arg_enterprise_id, &self.opt.arg_collection_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _collections_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.collections().delete(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("collection-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _collections_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.collections().get(&self.opt.arg_enterprise_id, &self.opt.arg_collection_id); - for parg in self.opt.arg_v.iter() { + fn _collections_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.collections().get(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("collection-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _collections_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _collections_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Collection::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -231,106 +177,115 @@ impl Engine { request.collection_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["collection-id", "kind", "name", "product-id", "visibility"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.collections().insert(request, &self.opt.arg_enterprise_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.collections().insert(request, opt.value_of("enterprise-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _collections_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.collections().list(&self.opt.arg_enterprise_id); - for parg in self.opt.arg_v.iter() { + fn _collections_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.collections().list(opt.value_of("enterprise-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _collections_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _collections_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Collection::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -364,60 +319,65 @@ impl Engine { request.collection_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["collection-id", "kind", "name", "product-id", "visibility"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.collections().patch(request, &self.opt.arg_enterprise_id, &self.opt.arg_collection_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.collections().patch(request, opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("collection-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _collections_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _collections_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Collection::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -451,196 +411,208 @@ impl Engine { request.collection_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["collection-id", "kind", "name", "product-id", "visibility"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.collections().update(request, &self.opt.arg_enterprise_id, &self.opt.arg_collection_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.collections().update(request, opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("collection-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _collectionviewers_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.collectionviewers().delete(&self.opt.arg_enterprise_id, &self.opt.arg_collection_id, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _collectionviewers_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.collectionviewers().delete(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("collection-id").unwrap_or(""), opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _collectionviewers_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.collectionviewers().get(&self.opt.arg_enterprise_id, &self.opt.arg_collection_id, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _collectionviewers_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.collectionviewers().get(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("collection-id").unwrap_or(""), opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _collectionviewers_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.collectionviewers().list(&self.opt.arg_enterprise_id, &self.opt.arg_collection_id); - for parg in self.opt.arg_v.iter() { + fn _collectionviewers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.collectionviewers().list(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("collection-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _collectionviewers_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _collectionviewers_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::User::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -665,60 +637,65 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "kind", "primary-email"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.collectionviewers().patch(request, &self.opt.arg_enterprise_id, &self.opt.arg_collection_id, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.collectionviewers().patch(request, opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("collection-id").unwrap_or(""), opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _collectionviewers_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _collectionviewers_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::User::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -743,198 +720,215 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "kind", "primary-email"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.collectionviewers().update(request, &self.opt.arg_enterprise_id, &self.opt.arg_collection_id, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.collectionviewers().update(request, opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("collection-id").unwrap_or(""), opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _devices_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.devices().get(&self.opt.arg_enterprise_id, &self.opt.arg_user_id, &self.opt.arg_device_id); - for parg in self.opt.arg_v.iter() { + fn _devices_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.devices().get(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or(""), opt.value_of("device-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _devices_get_state(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.devices().get_state(&self.opt.arg_enterprise_id, &self.opt.arg_user_id, &self.opt.arg_device_id); - for parg in self.opt.arg_v.iter() { + fn _devices_get_state(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.devices().get_state(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or(""), opt.value_of("device-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _devices_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.devices().list(&self.opt.arg_enterprise_id, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _devices_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.devices().list(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _devices_set_state(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _devices_set_state(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::DeviceState::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -956,104 +950,108 @@ impl Engine { request.account_state = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-state", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.devices().set_state(request, &self.opt.arg_enterprise_id, &self.opt.arg_user_id, &self.opt.arg_device_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.devices().set_state(request, opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or(""), opt.value_of("device-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _enterprises_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.enterprises().delete(&self.opt.arg_enterprise_id); - for parg in self.opt.arg_v.iter() { + fn _enterprises_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.enterprises().delete(opt.value_of("enterprise-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _enterprises_enroll(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _enterprises_enroll(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Enterprise::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1081,106 +1079,115 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "kind", "name", "primary-domain"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.enterprises().enroll(request, &self.opt.arg_token); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.enterprises().enroll(request, opt.value_of("token").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _enterprises_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.enterprises().get(&self.opt.arg_enterprise_id); - for parg in self.opt.arg_v.iter() { + fn _enterprises_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.enterprises().get(opt.value_of("enterprise-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _enterprises_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _enterprises_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Enterprise::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1208,106 +1215,115 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "kind", "name", "primary-domain"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.enterprises().insert(request, &self.opt.arg_token); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.enterprises().insert(request, opt.value_of("token").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _enterprises_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.enterprises().list(&self.opt.arg_domain); - for parg in self.opt.arg_v.iter() { + fn _enterprises_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.enterprises().list(opt.value_of("domain").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _enterprises_set_account(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _enterprises_set_account(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::EnterpriseAccount::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1329,240 +1345,251 @@ impl Engine { request.account_email = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-email", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.enterprises().set_account(request, &self.opt.arg_enterprise_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.enterprises().set_account(request, opt.value_of("enterprise-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _enterprises_unenroll(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.enterprises().unenroll(&self.opt.arg_enterprise_id); - for parg in self.opt.arg_v.iter() { + fn _enterprises_unenroll(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.enterprises().unenroll(opt.value_of("enterprise-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _entitlements_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.entitlements().delete(&self.opt.arg_enterprise_id, &self.opt.arg_user_id, &self.opt.arg_entitlement_id); - for parg in self.opt.arg_v.iter() { + fn _entitlements_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.entitlements().delete(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or(""), opt.value_of("entitlement-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _entitlements_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.entitlements().get(&self.opt.arg_enterprise_id, &self.opt.arg_user_id, &self.opt.arg_entitlement_id); - for parg in self.opt.arg_v.iter() { + fn _entitlements_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.entitlements().get(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or(""), opt.value_of("entitlement-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _entitlements_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.entitlements().list(&self.opt.arg_enterprise_id, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _entitlements_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.entitlements().list(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _entitlements_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _entitlements_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Entitlement::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1587,63 +1614,68 @@ impl Engine { request.product_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind", "product-id", "reason"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.entitlements().patch(request, &self.opt.arg_enterprise_id, &self.opt.arg_user_id, &self.opt.arg_entitlement_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.entitlements().patch(request, opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or(""), opt.value_of("entitlement-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "install" => { call = call.install(arg_from_str(value.unwrap_or("false"), err, "install", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["install"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _entitlements_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _entitlements_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Entitlement::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1668,337 +1700,361 @@ impl Engine { request.product_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind", "product-id", "reason"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.entitlements().update(request, &self.opt.arg_enterprise_id, &self.opt.arg_user_id, &self.opt.arg_entitlement_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.entitlements().update(request, opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or(""), opt.value_of("entitlement-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "install" => { call = call.install(arg_from_str(value.unwrap_or("false"), err, "install", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["install"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _grouplicenses_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.grouplicenses().get(&self.opt.arg_enterprise_id, &self.opt.arg_group_license_id); - for parg in self.opt.arg_v.iter() { + fn _grouplicenses_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.grouplicenses().get(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("group-license-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _grouplicenses_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.grouplicenses().list(&self.opt.arg_enterprise_id); - for parg in self.opt.arg_v.iter() { + fn _grouplicenses_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.grouplicenses().list(opt.value_of("enterprise-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _grouplicenseusers_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.grouplicenseusers().list(&self.opt.arg_enterprise_id, &self.opt.arg_group_license_id); - for parg in self.opt.arg_v.iter() { + fn _grouplicenseusers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.grouplicenseusers().list(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("group-license-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _installs_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.installs().delete(&self.opt.arg_enterprise_id, &self.opt.arg_user_id, &self.opt.arg_device_id, &self.opt.arg_install_id); - for parg in self.opt.arg_v.iter() { + fn _installs_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.installs().delete(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or(""), opt.value_of("device-id").unwrap_or(""), opt.value_of("install-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _installs_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.installs().get(&self.opt.arg_enterprise_id, &self.opt.arg_user_id, &self.opt.arg_device_id, &self.opt.arg_install_id); - for parg in self.opt.arg_v.iter() { + fn _installs_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.installs().get(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or(""), opt.value_of("device-id").unwrap_or(""), opt.value_of("install-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _installs_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.installs().list(&self.opt.arg_enterprise_id, &self.opt.arg_user_id, &self.opt.arg_device_id); - for parg in self.opt.arg_v.iter() { + fn _installs_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.installs().list(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or(""), opt.value_of("device-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _installs_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _installs_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Install::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2026,60 +2082,65 @@ impl Engine { request.product_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["install-state", "kind", "product-id", "version-code"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.installs().patch(request, &self.opt.arg_enterprise_id, &self.opt.arg_user_id, &self.opt.arg_device_id, &self.opt.arg_install_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.installs().patch(request, opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or(""), opt.value_of("device-id").unwrap_or(""), opt.value_of("install-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _installs_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _installs_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Install::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2107,253 +2168,274 @@ impl Engine { request.product_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["install-state", "kind", "product-id", "version-code"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.installs().update(request, &self.opt.arg_enterprise_id, &self.opt.arg_user_id, &self.opt.arg_device_id, &self.opt.arg_install_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.installs().update(request, opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or(""), opt.value_of("device-id").unwrap_or(""), opt.value_of("install-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _permissions_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.permissions().get(&self.opt.arg_permission_id); - for parg in self.opt.arg_v.iter() { + fn _permissions_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.permissions().get(opt.value_of("permission-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _products_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.products().get(&self.opt.arg_enterprise_id, &self.opt.arg_product_id); - for parg in self.opt.arg_v.iter() { + fn _products_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.products().get(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("product-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _products_get_app_restrictions_schema(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.products().get_app_restrictions_schema(&self.opt.arg_enterprise_id, &self.opt.arg_product_id); - for parg in self.opt.arg_v.iter() { + fn _products_get_app_restrictions_schema(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.products().get_app_restrictions_schema(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("product-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _products_get_permissions(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.products().get_permissions(&self.opt.arg_enterprise_id, &self.opt.arg_product_id); - for parg in self.opt.arg_v.iter() { + fn _products_get_permissions(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.products().get_permissions(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("product-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _products_update_permissions(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _products_update_permissions(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ProductPermissions::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2375,399 +2457,497 @@ impl Engine { request.product_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind", "product-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.products().update_permissions(request, &self.opt.arg_enterprise_id, &self.opt.arg_product_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.products().update_permissions(request, opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("product-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_generate_token(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.users().generate_token(&self.opt.arg_enterprise_id, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _users_generate_token(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().generate_token(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.users().get(&self.opt.arg_enterprise_id, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _users_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().get(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.users().list(&self.opt.arg_enterprise_id, &self.opt.arg_email); - for parg in self.opt.arg_v.iter() { + fn _users_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().list(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("email").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_revoke_token(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.users().revoke_token(&self.opt.arg_enterprise_id, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _users_revoke_token(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().revoke_token(opt.value_of("enterprise-id").unwrap_or(""), opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_collections { - if self.opt.cmd_delete { - call_result = self._collections_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._collections_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._collections_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._collections_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._collections_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._collections_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("collections", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._collections_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._collections_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._collections_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._collections_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._collections_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._collections_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("collections".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("collectionviewers", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._collectionviewers_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._collectionviewers_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._collectionviewers_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._collectionviewers_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._collectionviewers_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("collectionviewers".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("devices", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._devices_get(opt, dry_run, &mut err); + }, + ("get-state", Some(opt)) => { + call_result = self._devices_get_state(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._devices_list(opt, dry_run, &mut err); + }, + ("set-state", Some(opt)) => { + call_result = self._devices_set_state(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("devices".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("enterprises", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._enterprises_delete(opt, dry_run, &mut err); + }, + ("enroll", Some(opt)) => { + call_result = self._enterprises_enroll(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._enterprises_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._enterprises_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._enterprises_list(opt, dry_run, &mut err); + }, + ("set-account", Some(opt)) => { + call_result = self._enterprises_set_account(opt, dry_run, &mut err); + }, + ("unenroll", Some(opt)) => { + call_result = self._enterprises_unenroll(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("enterprises".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("entitlements", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._entitlements_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._entitlements_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._entitlements_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._entitlements_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._entitlements_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("entitlements".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("grouplicenses", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._grouplicenses_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._grouplicenses_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("grouplicenses".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("grouplicenseusers", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._grouplicenseusers_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("grouplicenseusers".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("installs", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._installs_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._installs_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._installs_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._installs_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._installs_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("installs".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("permissions", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._permissions_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("permissions".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("products", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._products_get(opt, dry_run, &mut err); + }, + ("get-app-restrictions-schema", Some(opt)) => { + call_result = self._products_get_app_restrictions_schema(opt, dry_run, &mut err); + }, + ("get-permissions", Some(opt)) => { + call_result = self._products_get_permissions(opt, dry_run, &mut err); + }, + ("update-permissions", Some(opt)) => { + call_result = self._products_update_permissions(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("products".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("users", Some(opt)) => { + match opt.subcommand() { + ("generate-token", Some(opt)) => { + call_result = self._users_generate_token(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._users_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._users_list(opt, dry_run, &mut err); + }, + ("revoke-token", Some(opt)) => { + call_result = self._users_revoke_token(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("users".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_collectionviewers { - if self.opt.cmd_delete { - call_result = self._collectionviewers_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._collectionviewers_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._collectionviewers_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._collectionviewers_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._collectionviewers_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_devices { - if self.opt.cmd_get { - call_result = self._devices_get(dry_run, &mut err); - } else if self.opt.cmd_get_state { - call_result = self._devices_get_state(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._devices_list(dry_run, &mut err); - } else if self.opt.cmd_set_state { - call_result = self._devices_set_state(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_enterprises { - if self.opt.cmd_delete { - call_result = self._enterprises_delete(dry_run, &mut err); - } else if self.opt.cmd_enroll { - call_result = self._enterprises_enroll(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._enterprises_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._enterprises_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._enterprises_list(dry_run, &mut err); - } else if self.opt.cmd_set_account { - call_result = self._enterprises_set_account(dry_run, &mut err); - } else if self.opt.cmd_unenroll { - call_result = self._enterprises_unenroll(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_entitlements { - if self.opt.cmd_delete { - call_result = self._entitlements_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._entitlements_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._entitlements_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._entitlements_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._entitlements_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_grouplicenses { - if self.opt.cmd_get { - call_result = self._grouplicenses_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._grouplicenses_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_grouplicenseusers { - if self.opt.cmd_list { - call_result = self._grouplicenseusers_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_installs { - if self.opt.cmd_delete { - call_result = self._installs_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._installs_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._installs_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._installs_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._installs_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_permissions { - if self.opt.cmd_get { - call_result = self._permissions_get(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_products { - if self.opt.cmd_get { - call_result = self._products_get(dry_run, &mut err); - } else if self.opt.cmd_get_app_restrictions_schema { - call_result = self._products_get_app_restrictions_schema(dry_run, &mut err); - } else if self.opt.cmd_get_permissions { - call_result = self._products_get_permissions(dry_run, &mut err); - } else if self.opt.cmd_update_permissions { - call_result = self._products_update_permissions(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_users { - if self.opt.cmd_generate_token { - call_result = self._users_generate_token(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._users_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._users_list(dry_run, &mut err); - } else if self.opt.cmd_revoke_token { - call_result = self._users_revoke_token(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -2780,7 +2960,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2793,7 +2973,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2803,37 +2983,1484 @@ impl Engine { let engine = Engine { opt: opt, hub: api::AndroidEnterprise::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("collections", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes a collection."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/collections_delete", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"collection-id"##), + None, + Some(r##"The ID of the collection."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves the details of a collection."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/collections_get", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"collection-id"##), + None, + Some(r##"The ID of the collection."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new collection."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/collections_insert", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the IDs of all the collections for an enterprise."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/collections_list", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a collection. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/collections_patch", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"collection-id"##), + None, + Some(r##"The ID of the collection."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a collection."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/collections_update", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"collection-id"##), + None, + Some(r##"The ID of the collection."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("collectionviewers", "methods: 'delete', 'get', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Removes the user from the list of those specifically allowed to see the collection. If the collection's visibility is set to viewersOnly then only such users will see the collection."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/collectionviewers_delete", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"collection-id"##), + None, + Some(r##"The ID of the collection."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves the ID of the user if they have been specifically allowed to see the collection. If the collection's visibility is set to viewersOnly then only these users will see the collection."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/collectionviewers_get", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"collection-id"##), + None, + Some(r##"The ID of the collection."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the IDs of the users who have been specifically allowed to see the collection. If the collection's visibility is set to viewersOnly then only these users will see the collection."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/collectionviewers_list", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"collection-id"##), + None, + Some(r##"The ID of the collection."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Adds the user to the list of those specifically allowed to see the collection. If the collection's visibility is set to viewersOnly then only such users will see the collection. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/collectionviewers_patch", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"collection-id"##), + None, + Some(r##"The ID of the collection."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Adds the user to the list of those specifically allowed to see the collection. If the collection's visibility is set to viewersOnly then only such users will see the collection."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/collectionviewers_update", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"collection-id"##), + None, + Some(r##"The ID of the collection."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("devices", "methods: 'get', 'get-state', 'list' and 'set-state'", vec![ + ("get", + Some(r##"Retrieves the details of a device."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/devices_get", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"device-id"##), + None, + Some(r##"The ID of the device."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-state", + Some(r##"Retrieves whether a device is enabled or disabled for access by the user to Google services. The device state takes effect only if enforcing EMM policies on Android devices is enabled in the Google Admin Console. Otherwise, the device state is ignored and all devices are allowed access to Google services."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/devices_get-state", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"device-id"##), + None, + Some(r##"The ID of the device."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the IDs of all of a user's devices."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/devices_list", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-state", + Some(r##"Sets whether a device is enabled or disabled for access by the user to Google services. The device state takes effect only if enforcing EMM policies on Android devices is enabled in the Google Admin Console. Otherwise, the device state is ignored and all devices are allowed access to Google services."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/devices_set-state", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"device-id"##), + None, + Some(r##"The ID of the device."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("enterprises", "methods: 'delete', 'enroll', 'get', 'insert', 'list', 'set-account' and 'unenroll'", vec![ + ("delete", + Some(r##"Deletes the binding between the MDM and enterprise. This is now deprecated; use this to unenroll customers that were previously enrolled with the 'insert' call, then enroll them again with the 'enroll' call."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/enterprises_delete", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("enroll", + Some(r##"Enrolls an enterprise with the calling MDM."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/enterprises_enroll", + vec![ + (Some(r##"token"##), + None, + Some(r##"The token provided by the enterprise to register the MDM."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Retrieves the name and domain of an enterprise."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/enterprises_get", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Establishes the binding between the MDM and an enterprise. This is now deprecated; use enroll instead."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/enterprises_insert", + vec![ + (Some(r##"token"##), + None, + Some(r##"The token provided by the enterprise to register the MDM."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Looks up an enterprise by domain name."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/enterprises_list", + vec![ + (Some(r##"domain"##), + None, + Some(r##"The exact primary domain name of the enterprise to look up."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-account", + Some(r##"Set the account that will be used to authenticate to the API as the enterprise."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/enterprises_set-account", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("unenroll", + Some(r##"Unenrolls an enterprise from the calling MDM."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/enterprises_unenroll", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("entitlements", "methods: 'delete', 'get', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Removes an entitlement to an app for a user and uninstalls it."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/entitlements_delete", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"entitlement-id"##), + None, + Some(r##"The ID of the entitlement, e.g. "app:com.google.android.gm"."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves details of an entitlement."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/entitlements_get", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"entitlement-id"##), + None, + Some(r##"The ID of the entitlement, e.g. "app:com.google.android.gm"."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List of all entitlements for the specified user. Only the ID is set."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/entitlements_list", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Adds or updates an entitlement to an app for a user. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/entitlements_patch", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"entitlement-id"##), + None, + Some(r##"The ID of the entitlement, e.g. "app:com.google.android.gm"."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Adds or updates an entitlement to an app for a user."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/entitlements_update", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"entitlement-id"##), + None, + Some(r##"The ID of the entitlement, e.g. "app:com.google.android.gm"."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("grouplicenses", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Retrieves details of an enterprise's group license for a product."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/grouplicenses_get", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"group-license-id"##), + None, + Some(r##"The ID of the product the group license is for, e.g. "app:com.google.android.gm"."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves IDs of all products for which the enterprise has a group license."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/grouplicenses_list", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("grouplicenseusers", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves the IDs of the users who have been granted entitlements under the license."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/grouplicenseusers_list", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"group-license-id"##), + None, + Some(r##"The ID of the product the group license is for, e.g. "app:com.google.android.gm"."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("installs", "methods: 'delete', 'get', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Requests to remove an app from a device. A call to get or list will still show the app as installed on the device until it is actually removed."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/installs_delete", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"device-id"##), + None, + Some(r##"The Android ID of the device."##), + Some(true), + Some(false)), + + (Some(r##"install-id"##), + None, + Some(r##"The ID of the product represented by the install, e.g. "app:com.google.android.gm"."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves details of an installation of an app on a device."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/installs_get", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"device-id"##), + None, + Some(r##"The Android ID of the device."##), + Some(true), + Some(false)), + + (Some(r##"install-id"##), + None, + Some(r##"The ID of the product represented by the install, e.g. "app:com.google.android.gm"."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the details of all apps installed on the specified device."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/installs_list", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"device-id"##), + None, + Some(r##"The Android ID of the device."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Requests to install the latest version of an app to a device. If the app is already installed then it is updated to the latest version if necessary. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/installs_patch", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"device-id"##), + None, + Some(r##"The Android ID of the device."##), + Some(true), + Some(false)), + + (Some(r##"install-id"##), + None, + Some(r##"The ID of the product represented by the install, e.g. "app:com.google.android.gm"."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Requests to install the latest version of an app to a device. If the app is already installed then it is updated to the latest version if necessary."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/installs_update", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"device-id"##), + None, + Some(r##"The Android ID of the device."##), + Some(true), + Some(false)), + + (Some(r##"install-id"##), + None, + Some(r##"The ID of the product represented by the install, e.g. "app:com.google.android.gm"."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("permissions", "methods: 'get'", vec![ + ("get", + Some(r##"Retrieves details of an Android app permission for display to an enterprise admin."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/permissions_get", + vec![ + (Some(r##"permission-id"##), + None, + Some(r##"The ID of the permission."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("products", "methods: 'get', 'get-app-restrictions-schema', 'get-permissions' and 'update-permissions'", vec![ + ("get", + Some(r##"Retrieves details of a product for display to an enterprise admin."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/products_get", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"product-id"##), + None, + Some(r##"The ID of the product, e.g. "app:com.google.android.gm"."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-app-restrictions-schema", + Some(r##"Retrieves the schema defining app restrictions configurable for this product. All products have a schema, but this may be empty if no app restrictions are defined."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/products_get-app-restrictions-schema", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"product-id"##), + None, + Some(r##"The ID of the product."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-permissions", + Some(r##"Retrieves the Android app permissions required by this app."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/products_get-permissions", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"product-id"##), + None, + Some(r##"The ID of the product."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update-permissions", + Some(r##"Updates the set of Android app permissions for this app that have been accepted by the enterprise."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/products_update-permissions", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"product-id"##), + None, + Some(r##"The ID of the product."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("users", "methods: 'generate-token', 'get', 'list' and 'revoke-token'", vec![ + ("generate-token", + Some(r##"Generates a token (activation code) to allow this user to configure their work account in the Android Setup Wizard. Revokes any previously generated token."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/users_generate-token", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Retrieves a user's details."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/users_get", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Looks up a user by email address."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/users_list", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"email"##), + None, + Some(r##"The exact primary email address of the user to look up."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("revoke-token", + Some(r##"Revokes a previously generated token (activation code) for the user."##), + "Details at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli/users_revoke-token", + vec![ + (Some(r##"enterprise-id"##), + None, + Some(r##"The ID of the enterprise."##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ]; + + let mut app = App::new("androidenterprise1") + .author("Sebastian Thiel ") + .version("0.2.0+20150309") + .about("Allows MDMs/EMMs and enterprises to manage the deployment of apps to Android for Work users.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_androidenterprise1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/androidenterprise1/Cargo.toml b/gen/androidenterprise1/Cargo.toml index c6248aaa13..e9015e2a5f 100644 --- a/gen/androidenterprise1/Cargo.toml +++ b/gen/androidenterprise1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-androidenterprise1" -version = "0.1.6+20150309" +version = "0.1.7+20150309" authors = ["Sebastian Thiel "] description = "A complete library to interact with Android Enterprise (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/androidenterprise1" @@ -14,9 +14,10 @@ keywords = ["androidenterprise", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/androidenterprise1/README.md b/gen/androidenterprise1/README.md index 7bd538e025..26b02dafd7 100644 --- a/gen/androidenterprise1/README.md +++ b/gen/androidenterprise1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-androidenterprise1` library allows access to all features of the *Google Android Enterprise* service. -This documentation was generated from *Android Enterprise* crate version *0.1.6+20150309*, where *20150309* is the exact revision of the *androidenterprise:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *Android Enterprise* crate version *0.1.7+20150309*, where *20150309* is the exact revision of the *androidenterprise:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. # Features Handle the following *Resources* with ease from the central [hub](http://byron.github.io/google-apis-rs/google_androidenterprise1/struct.AndroidEnterprise.html) ... @@ -186,7 +186,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_androidenterprise1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_androidenterprise1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/androidenterprise1/src/cmn.rs b/gen/androidenterprise1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/androidenterprise1/src/cmn.rs +++ b/gen/androidenterprise1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/androidenterprise1/src/lib.rs b/gen/androidenterprise1/src/lib.rs index 9c809cc95f..e017f7f4c1 100644 --- a/gen/androidenterprise1/src/lib.rs +++ b/gen/androidenterprise1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *Android Enterprise* crate version *0.1.6+20150309*, where *20150309* is the exact revision of the *androidenterprise:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *Android Enterprise* crate version *0.1.7+20150309*, where *20150309* is the exact revision of the *androidenterprise:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! The original source code is [on github](https://github.com/Byron/google-apis-rs/tree/master/gen/androidenterprise1). //! # Features //! @@ -187,7 +187,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -196,7 +196,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -212,6 +211,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -334,7 +334,7 @@ impl<'a, C, A> AndroidEnterprise AndroidEnterprise { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -373,7 +373,7 @@ impl<'a, C, A> AndroidEnterprise } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -2532,7 +2532,7 @@ impl<'a, C, A> CollectionviewerDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2554,7 +2554,7 @@ impl<'a, C, A> CollectionviewerDeleteCall<'a, C, A> where C: BorrowMut CollectionviewerPatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, User)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2792,11 +2793,20 @@ impl<'a, C, A> CollectionviewerPatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2819,7 +2829,7 @@ impl<'a, C, A> CollectionviewerPatchCall<'a, C, A> where C: BorrowMut CollectionviewerGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3094,7 +3104,7 @@ impl<'a, C, A> CollectionviewerGetCall<'a, C, A> where C: BorrowMut CollectionviewerListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3355,7 +3365,7 @@ impl<'a, C, A> CollectionviewerListCall<'a, C, A> where C: BorrowMut CollectionviewerUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, User)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3593,11 +3604,20 @@ impl<'a, C, A> CollectionviewerUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3620,7 +3640,7 @@ impl<'a, C, A> CollectionviewerUpdateCall<'a, C, A> where C: BorrowMut UserRevokeTokenCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3892,7 +3912,7 @@ impl<'a, C, A> UserRevokeTokenCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4111,7 +4131,7 @@ impl<'a, C, A> UserGetCall<'a, C, A> where C: BorrowMut, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4133,7 +4153,7 @@ impl<'a, C, A> UserGetCall<'a, C, A> where C: BorrowMut, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4362,7 +4382,7 @@ impl<'a, C, A> UserListCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4384,7 +4404,7 @@ impl<'a, C, A> UserListCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4613,7 +4633,7 @@ impl<'a, C, A> UserGenerateTokenCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4635,7 +4655,7 @@ impl<'a, C, A> UserGenerateTokenCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4817,6 +4837,7 @@ impl<'a, C, A> InstallPatchCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Install)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4875,11 +4896,20 @@ impl<'a, C, A> InstallPatchCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4902,7 +4932,7 @@ impl<'a, C, A> InstallPatchCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5167,7 +5197,7 @@ impl<'a, C, A> InstallGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5189,7 +5219,7 @@ impl<'a, C, A> InstallGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5440,7 +5470,7 @@ impl<'a, C, A> InstallListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5462,7 +5492,7 @@ impl<'a, C, A> InstallListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5704,7 +5734,7 @@ impl<'a, C, A> InstallDeleteCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5726,7 +5756,7 @@ impl<'a, C, A> InstallDeleteCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5918,6 +5948,7 @@ impl<'a, C, A> InstallUpdateCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Install)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5976,11 +6007,20 @@ impl<'a, C, A> InstallUpdateCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6003,7 +6043,7 @@ impl<'a, C, A> InstallUpdateCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6216,6 +6256,7 @@ impl<'a, C, A> DeviceSetStateCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, DeviceState)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6273,11 +6314,20 @@ impl<'a, C, A> DeviceSetStateCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6300,7 +6350,7 @@ impl<'a, C, A> DeviceSetStateCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6553,7 +6603,7 @@ impl<'a, C, A> DeviceGetStateCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6575,7 +6625,7 @@ impl<'a, C, A> DeviceGetStateCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6814,7 +6864,7 @@ impl<'a, C, A> DeviceListCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6836,7 +6886,7 @@ impl<'a, C, A> DeviceListCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7067,7 +7117,7 @@ impl<'a, C, A> DeviceGetCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7089,7 +7139,7 @@ impl<'a, C, A> DeviceGetCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7325,7 +7375,7 @@ impl<'a, C, A> EnterpriseUnenrollCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7347,7 +7397,7 @@ impl<'a, C, A> EnterpriseUnenrollCall<'a, C, A> where C: BorrowMut EnterpriseInsertCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Enterprise)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7537,11 +7588,20 @@ impl<'a, C, A> EnterpriseInsertCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7564,7 +7624,7 @@ impl<'a, C, A> EnterpriseInsertCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7769,7 +7829,7 @@ impl<'a, C, A> EnterpriseListCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7791,7 +7851,7 @@ impl<'a, C, A> EnterpriseListCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8008,7 +8068,7 @@ impl<'a, C, A> EnterpriseGetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8030,7 +8090,7 @@ impl<'a, C, A> EnterpriseGetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8199,6 +8259,7 @@ impl<'a, C, A> EnterpriseEnrollCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Enterprise)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8230,11 +8291,20 @@ impl<'a, C, A> EnterpriseEnrollCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8257,7 +8327,7 @@ impl<'a, C, A> EnterpriseEnrollCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8438,6 +8508,7 @@ impl<'a, C, A> EnterpriseSetAccountCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, EnterpriseAccount)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8493,11 +8564,20 @@ impl<'a, C, A> EnterpriseSetAccountCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8520,7 +8600,7 @@ impl<'a, C, A> EnterpriseSetAccountCall<'a, C, A> where C: BorrowMut EnterpriseDeleteCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8770,7 +8850,7 @@ impl<'a, C, A> EnterpriseDeleteCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8929,6 +9009,7 @@ impl<'a, C, A> CollectionInsertCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Collection)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8984,11 +9065,20 @@ impl<'a, C, A> CollectionInsertCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9011,7 +9101,7 @@ impl<'a, C, A> CollectionInsertCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9193,6 +9283,7 @@ impl<'a, C, A> CollectionPatchCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Collection)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9249,11 +9340,20 @@ impl<'a, C, A> CollectionPatchCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9276,7 +9376,7 @@ impl<'a, C, A> CollectionPatchCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9468,6 +9568,7 @@ impl<'a, C, A> CollectionUpdateCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Collection)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9524,11 +9625,20 @@ impl<'a, C, A> CollectionUpdateCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9551,7 +9661,7 @@ impl<'a, C, A> CollectionUpdateCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9790,7 +9900,7 @@ impl<'a, C, A> CollectionListCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9812,7 +9922,7 @@ impl<'a, C, A> CollectionListCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10031,7 +10141,7 @@ impl<'a, C, A> CollectionGetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10053,7 +10163,7 @@ impl<'a, C, A> CollectionGetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10281,7 +10391,7 @@ impl<'a, C, A> CollectionDeleteCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10303,7 +10413,7 @@ impl<'a, C, A> CollectionDeleteCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10522,7 +10632,7 @@ impl<'a, C, A> GrouplicenseuserListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10544,7 +10654,7 @@ impl<'a, C, A> GrouplicenseuserListCall<'a, C, A> where C: BorrowMut EntitlementUpdateCall<'a, C, A> where C: BorrowMut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Entitlement)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10787,11 +10898,20 @@ impl<'a, C, A> EntitlementUpdateCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10814,7 +10934,7 @@ impl<'a, C, A> EntitlementUpdateCall<'a, C, A> where C: BorrowMut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11072,7 +11192,7 @@ impl<'a, C, A> EntitlementListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11094,7 +11214,7 @@ impl<'a, C, A> EntitlementListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11325,7 +11445,7 @@ impl<'a, C, A> EntitlementGetCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11347,7 +11467,7 @@ impl<'a, C, A> EntitlementGetCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11540,6 +11660,7 @@ impl<'a, C, A> EntitlementPatchCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Entitlement)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11600,11 +11721,20 @@ impl<'a, C, A> EntitlementPatchCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11627,7 +11757,7 @@ impl<'a, C, A> EntitlementPatchCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11886,7 +12016,7 @@ impl<'a, C, A> EntitlementDeleteCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11908,7 +12038,7 @@ impl<'a, C, A> EntitlementDeleteCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12137,7 +12267,7 @@ impl<'a, C, A> ProductGetPermissionCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12159,7 +12289,7 @@ impl<'a, C, A> ProductGetPermissionCall<'a, C, A> where C: BorrowMut ProductGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12415,7 +12545,7 @@ impl<'a, C, A> ProductGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12656,7 +12786,7 @@ impl<'a, C, A> ProductGetAppRestrictionsSchemaCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12678,7 +12808,7 @@ impl<'a, C, A> ProductGetAppRestrictionsSchemaCall<'a, C, A> where C: BorrowMut< access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12865,6 +12995,7 @@ impl<'a, C, A> ProductUpdatePermissionCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, ProductPermissions)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12921,11 +13052,20 @@ impl<'a, C, A> ProductUpdatePermissionCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12948,7 +13088,7 @@ impl<'a, C, A> ProductUpdatePermissionCall<'a, C, A> where C: BorrowMut GrouplicenseGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13211,7 +13351,7 @@ impl<'a, C, A> GrouplicenseGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -13438,7 +13578,7 @@ impl<'a, C, A> GrouplicenseListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13460,7 +13600,7 @@ impl<'a, C, A> GrouplicenseListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -13682,7 +13822,7 @@ impl<'a, C, A> PermissionGetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13704,7 +13844,7 @@ impl<'a, C, A> PermissionGetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/androidpublisher2-cli/Cargo.toml b/gen/androidpublisher2-cli/Cargo.toml index b1a0c16610..cbf0c3bd1b 100644 --- a/gen/androidpublisher2-cli/Cargo.toml +++ b/gen/androidpublisher2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-androidpublisher2-cli" -version = "0.1.0+20150323" +version = "0.2.0+20150323" authors = ["Sebastian Thiel "] description = "A complete library to interact with Android Publisher (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/androidpublisher2-cli" @@ -17,15 +17,14 @@ keywords = ["androidpublisher", "google", "cli"] name = "androidpublisher2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-androidpublisher2] path = "../androidpublisher2" diff --git a/gen/androidpublisher2-cli/README.md b/gen/androidpublisher2-cli/README.md index 068dc211a0..f5b39dd2a5 100644 --- a/gen/androidpublisher2-cli/README.md +++ b/gen/androidpublisher2-cli/README.md @@ -10,71 +10,75 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *Android Publisher* API can be found at the +[official documentation site](https://developers.google.com/android-publisher). + # Usage -This documentation was generated from the *Android Publisher* API at revision *20150323*. The CLI is at version *0.1.0*. +This documentation was generated from the *Android Publisher* API at revision *20150323*. The CLI is at version *0.2.0*. ```bash - androidpublisher2 [options] edits apklistings-delete [-p ...] - androidpublisher2 [options] edits apklistings-deleteall [-p ...] - androidpublisher2 [options] edits apklistings-get [-p ...] [-o ] - androidpublisher2 [options] edits apklistings-list [-p ...] [-o ] - androidpublisher2 [options] edits apklistings-patch -r ... [-p ...] [-o ] - androidpublisher2 [options] edits apklistings-update -r ... [-p ...] [-o ] - androidpublisher2 [options] edits apks-addexternallyhosted -r ... [-p ...] [-o ] - androidpublisher2 [options] edits apks-list [-p ...] [-o ] - androidpublisher2 [options] edits apks-upload -u (simple|resumable) [-p ...] [-o ] - androidpublisher2 [options] edits commit [-p ...] [-o ] - androidpublisher2 [options] edits delete [-p ...] - androidpublisher2 [options] edits details-get [-p ...] [-o ] - androidpublisher2 [options] edits details-patch -r ... [-p ...] [-o ] - androidpublisher2 [options] edits details-update -r ... [-p ...] [-o ] - androidpublisher2 [options] edits expansionfiles-get [-p ...] [-o ] - androidpublisher2 [options] edits expansionfiles-patch -r ... [-p ...] [-o ] - androidpublisher2 [options] edits expansionfiles-update -r ... [-p ...] [-o ] - androidpublisher2 [options] edits expansionfiles-upload -u (simple|resumable) [-p ...] [-o ] - androidpublisher2 [options] edits get [-p ...] [-o ] - androidpublisher2 [options] edits images-delete [-p ...] - androidpublisher2 [options] edits images-deleteall [-p ...] [-o ] - androidpublisher2 [options] edits images-list [-p ...] [-o ] - androidpublisher2 [options] edits images-upload -u (simple|resumable) [-p ...] [-o ] - androidpublisher2 [options] edits insert -r ... [-p ...] [-o ] - androidpublisher2 [options] edits listings-delete [-p ...] - androidpublisher2 [options] edits listings-deleteall [-p ...] - androidpublisher2 [options] edits listings-get [-p ...] [-o ] - androidpublisher2 [options] edits listings-list [-p ...] [-o ] - androidpublisher2 [options] edits listings-patch -r ... [-p ...] [-o ] - androidpublisher2 [options] edits listings-update -r ... [-p ...] [-o ] - androidpublisher2 [options] edits testers-get [-p ...] [-o ] - androidpublisher2 [options] edits testers-patch -r ... [-p ...] [-o ] - androidpublisher2 [options] edits testers-update -r ... [-p ...] [-o ] - androidpublisher2 [options] edits tracks-get [-p ...] [-o ] - androidpublisher2 [options] edits tracks-list [-p ...] [-o ] - androidpublisher2 [options] edits tracks-patch -r ... [-p ...] [-o ] - androidpublisher2 [options] edits tracks-update -r ... [-p ...] [-o ] - androidpublisher2 [options] edits validate [-p ...] [-o ] - androidpublisher2 [options] inappproducts batch -r ... [-p ...] [-o ] - androidpublisher2 [options] inappproducts delete [-p ...] - androidpublisher2 [options] inappproducts get [-p ...] [-o ] - androidpublisher2 [options] inappproducts insert -r ... [-p ...] [-o ] - androidpublisher2 [options] inappproducts list [-p ...] [-o ] - androidpublisher2 [options] inappproducts patch -r ... [-p ...] [-o ] - androidpublisher2 [options] inappproducts update -r ... [-p ...] [-o ] - androidpublisher2 [options] purchases products-get [-p ...] [-o ] - androidpublisher2 [options] purchases subscriptions-cancel [-p ...] - androidpublisher2 [options] purchases subscriptions-defer -r ... [-p ...] [-o ] - androidpublisher2 [options] purchases subscriptions-get [-p ...] [-o ] - androidpublisher2 [options] purchases subscriptions-refund [-p ...] - androidpublisher2 [options] purchases subscriptions-revoke [-p ...] +androidpublisher2 [options] + edits + apklistings-delete [-p ]... + apklistings-deleteall [-p ]... + apklistings-get [-p ]... [-o ] + apklistings-list [-p ]... [-o ] + apklistings-patch (-r )... [-p ]... [-o ] + apklistings-update (-r )... [-p ]... [-o ] + apks-addexternallyhosted (-r )... [-p ]... [-o ] + apks-list [-p ]... [-o ] + apks-upload (-u (simple|resumable) -f [-m ]) [-p ]... [-o ] + commit [-p ]... [-o ] + delete [-p ]... + details-get [-p ]... [-o ] + details-patch (-r )... [-p ]... [-o ] + details-update (-r )... [-p ]... [-o ] + expansionfiles-get [-p ]... [-o ] + expansionfiles-patch (-r )... [-p ]... [-o ] + expansionfiles-update (-r )... [-p ]... [-o ] + expansionfiles-upload (-u (simple|resumable) -f [-m ]) [-p ]... [-o ] + get [-p ]... [-o ] + images-delete [-p ]... + images-deleteall [-p ]... [-o ] + images-list [-p ]... [-o ] + images-upload (-u (simple|resumable) -f [-m ]) [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + listings-delete [-p ]... + listings-deleteall [-p ]... + listings-get [-p ]... [-o ] + listings-list [-p ]... [-o ] + listings-patch (-r )... [-p ]... [-o ] + listings-update (-r )... [-p ]... [-o ] + testers-get [-p ]... [-o ] + testers-patch (-r )... [-p ]... [-o ] + testers-update (-r )... [-p ]... [-o ] + tracks-get [-p ]... [-o ] + tracks-list [-p ]... [-o ] + tracks-patch (-r )... [-p ]... [-o ] + tracks-update (-r )... [-p ]... [-o ] + validate [-p ]... [-o ] + inappproducts + batch (-r )... [-p ]... [-o ] + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + purchases + products-get [-p ]... [-o ] + subscriptions-cancel [-p ]... + subscriptions-defer (-r )... [-p ]... [-o ] + subscriptions-get [-p ]... [-o ] + subscriptions-refund [-p ]... + subscriptions-revoke [-p ]... androidpublisher2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/androidpublisher2-cli/mkdocs.yml b/gen/androidpublisher2-cli/mkdocs.yml index ec320c2051..38fb28dd61 100644 --- a/gen/androidpublisher2-cli/mkdocs.yml +++ b/gen/androidpublisher2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Android Publisher v0.1.0+20150323 +site_name: Android Publisher v0.2.0+20150323 site_url: http://byron.github.io/google-apis-rs/google-androidpublisher2-cli site_description: Write integrating applications with bcore diff --git a/gen/androidpublisher2-cli/src/cmn.rs b/gen/androidpublisher2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/androidpublisher2-cli/src/cmn.rs +++ b/gen/androidpublisher2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/androidpublisher2-cli/src/main.rs b/gen/androidpublisher2-cli/src/main.rs index 95fd0dcc50..28f1a20a77 100644 --- a/gen/androidpublisher2-cli/src/main.rs +++ b/gen/androidpublisher2-cli/src/main.rs @@ -2,303 +2,245 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_androidpublisher2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - androidpublisher2 [options] edits apklistings-delete [-p ...] - androidpublisher2 [options] edits apklistings-deleteall [-p ...] - androidpublisher2 [options] edits apklistings-get [-p ...] [-o ] - androidpublisher2 [options] edits apklistings-list [-p ...] [-o ] - androidpublisher2 [options] edits apklistings-patch -r ... [-p ...] [-o ] - androidpublisher2 [options] edits apklistings-update -r ... [-p ...] [-o ] - androidpublisher2 [options] edits apks-addexternallyhosted -r ... [-p ...] [-o ] - androidpublisher2 [options] edits apks-list [-p ...] [-o ] - androidpublisher2 [options] edits apks-upload -u (simple|resumable) [-p ...] [-o ] - androidpublisher2 [options] edits commit [-p ...] [-o ] - androidpublisher2 [options] edits delete [-p ...] - androidpublisher2 [options] edits details-get [-p ...] [-o ] - androidpublisher2 [options] edits details-patch -r ... [-p ...] [-o ] - androidpublisher2 [options] edits details-update -r ... [-p ...] [-o ] - androidpublisher2 [options] edits expansionfiles-get [-p ...] [-o ] - androidpublisher2 [options] edits expansionfiles-patch -r ... [-p ...] [-o ] - androidpublisher2 [options] edits expansionfiles-update -r ... [-p ...] [-o ] - androidpublisher2 [options] edits expansionfiles-upload -u (simple|resumable) [-p ...] [-o ] - androidpublisher2 [options] edits get [-p ...] [-o ] - androidpublisher2 [options] edits images-delete [-p ...] - androidpublisher2 [options] edits images-deleteall [-p ...] [-o ] - androidpublisher2 [options] edits images-list [-p ...] [-o ] - androidpublisher2 [options] edits images-upload -u (simple|resumable) [-p ...] [-o ] - androidpublisher2 [options] edits insert -r ... [-p ...] [-o ] - androidpublisher2 [options] edits listings-delete [-p ...] - androidpublisher2 [options] edits listings-deleteall [-p ...] - androidpublisher2 [options] edits listings-get [-p ...] [-o ] - androidpublisher2 [options] edits listings-list [-p ...] [-o ] - androidpublisher2 [options] edits listings-patch -r ... [-p ...] [-o ] - androidpublisher2 [options] edits listings-update -r ... [-p ...] [-o ] - androidpublisher2 [options] edits testers-get [-p ...] [-o ] - androidpublisher2 [options] edits testers-patch -r ... [-p ...] [-o ] - androidpublisher2 [options] edits testers-update -r ... [-p ...] [-o ] - androidpublisher2 [options] edits tracks-get [-p ...] [-o ] - androidpublisher2 [options] edits tracks-list [-p ...] [-o ] - androidpublisher2 [options] edits tracks-patch -r ... [-p ...] [-o ] - androidpublisher2 [options] edits tracks-update -r ... [-p ...] [-o ] - androidpublisher2 [options] edits validate [-p ...] [-o ] - androidpublisher2 [options] inappproducts batch -r ... [-p ...] [-o ] - androidpublisher2 [options] inappproducts delete [-p ...] - androidpublisher2 [options] inappproducts get [-p ...] [-o ] - androidpublisher2 [options] inappproducts insert -r ... [-p ...] [-o ] - androidpublisher2 [options] inappproducts list [-p ...] [-o ] - androidpublisher2 [options] inappproducts patch -r ... [-p ...] [-o ] - androidpublisher2 [options] inappproducts update -r ... [-p ...] [-o ] - androidpublisher2 [options] purchases products-get [-p ...] [-o ] - androidpublisher2 [options] purchases subscriptions-cancel [-p ...] - androidpublisher2 [options] purchases subscriptions-defer -r ... [-p ...] [-o ] - androidpublisher2 [options] purchases subscriptions-get [-p ...] [-o ] - androidpublisher2 [options] purchases subscriptions-refund [-p ...] - androidpublisher2 [options] purchases subscriptions-revoke [-p ...] - androidpublisher2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::AndroidPublisher>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _edits_apklistings_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let apk_version_code: i32 = arg_from_str(&self.opt.arg_apk_version_code, err, "", "integer"); - let mut call = self.hub.edits().apklistings_delete(&self.opt.arg_package_name, &self.opt.arg_edit_id, apk_version_code, &self.opt.arg_language); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _edits_apklistings_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let apk_version_code: i32 = arg_from_str(&opt.value_of("apk-version-code").unwrap_or(""), err, "", "integer"); + let mut call = self.hub.edits().apklistings_delete(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), apk_version_code, opt.value_of("language").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _edits_apklistings_deleteall(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let apk_version_code: i32 = arg_from_str(&self.opt.arg_apk_version_code, err, "", "integer"); - let mut call = self.hub.edits().apklistings_deleteall(&self.opt.arg_package_name, &self.opt.arg_edit_id, apk_version_code); - for parg in self.opt.arg_v.iter() { + fn _edits_apklistings_deleteall(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let apk_version_code: i32 = arg_from_str(&opt.value_of("apk-version-code").unwrap_or(""), err, "", "integer"); + let mut call = self.hub.edits().apklistings_deleteall(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), apk_version_code); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _edits_apklistings_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let apk_version_code: i32 = arg_from_str(&self.opt.arg_apk_version_code, err, "", "integer"); - let mut call = self.hub.edits().apklistings_get(&self.opt.arg_package_name, &self.opt.arg_edit_id, apk_version_code, &self.opt.arg_language); - for parg in self.opt.arg_v.iter() { + fn _edits_apklistings_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let apk_version_code: i32 = arg_from_str(&opt.value_of("apk-version-code").unwrap_or(""), err, "", "integer"); + let mut call = self.hub.edits().apklistings_get(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), apk_version_code, opt.value_of("language").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_apklistings_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let apk_version_code: i32 = arg_from_str(&self.opt.arg_apk_version_code, err, "", "integer"); - let mut call = self.hub.edits().apklistings_list(&self.opt.arg_package_name, &self.opt.arg_edit_id, apk_version_code); - for parg in self.opt.arg_v.iter() { + fn _edits_apklistings_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let apk_version_code: i32 = arg_from_str(&opt.value_of("apk-version-code").unwrap_or(""), err, "", "integer"); + let mut call = self.hub.edits().apklistings_list(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), apk_version_code); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_apklistings_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _edits_apklistings_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ApkListing::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -320,61 +262,66 @@ impl Engine { request.language = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["language", "recent-changes"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let apk_version_code: i32 = arg_from_str(&self.opt.arg_apk_version_code, err, "", "integer"); - let mut call = self.hub.edits().apklistings_patch(request, &self.opt.arg_package_name, &self.opt.arg_edit_id, apk_version_code, &self.opt.arg_language); - for parg in self.opt.arg_v.iter() { + let apk_version_code: i32 = arg_from_str(&opt.value_of("apk-version-code").unwrap_or(""), err, "", "integer"); + let mut call = self.hub.edits().apklistings_patch(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), apk_version_code, opt.value_of("language").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_apklistings_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _edits_apklistings_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ApkListing::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -396,61 +343,66 @@ impl Engine { request.language = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["language", "recent-changes"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let apk_version_code: i32 = arg_from_str(&self.opt.arg_apk_version_code, err, "", "integer"); - let mut call = self.hub.edits().apklistings_update(request, &self.opt.arg_package_name, &self.opt.arg_edit_id, apk_version_code, &self.opt.arg_language); - for parg in self.opt.arg_v.iter() { + let apk_version_code: i32 = arg_from_str(&opt.value_of("apk-version-code").unwrap_or(""), err, "", "integer"); + let mut call = self.hub.edits().apklistings_update(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), apk_version_code, opt.value_of("language").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_apks_addexternallyhosted(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _edits_apks_addexternallyhosted(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ApksAddExternallyHostedRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -537,298 +489,312 @@ impl Engine { request.externally_hosted_apk.as_mut().unwrap().native_codes.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["application-label", "certificate-base64s", "externally-hosted-apk", "externally-hosted-url", "file-sha1-base64", "file-sha256-base64", "file-size", "icon-base64", "maximum-sdk", "minimum-sdk", "native-codes", "package-name", "uses-features", "version-code", "version-name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.edits().apks_addexternallyhosted(request, &self.opt.arg_package_name, &self.opt.arg_edit_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.edits().apks_addexternallyhosted(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _edits_apks_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().apks_list(&self.opt.arg_package_name, &self.opt.arg_edit_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _edits_apks_upload(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().apks_upload(&self.opt.arg_package_name, &self.opt.arg_edit_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_commit(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().commit(&self.opt.arg_package_name, &self.opt.arg_edit_id); - for parg in self.opt.arg_v.iter() { + fn _edits_apks_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().apks_list(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().delete(&self.opt.arg_package_name, &self.opt.arg_edit_id); - for parg in self.opt.arg_v.iter() { + fn _edits_apks_upload(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().apks_upload(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _edits_commit(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().commit(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _edits_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().delete(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _edits_details_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().details_get(&self.opt.arg_package_name, &self.opt.arg_edit_id); - for parg in self.opt.arg_v.iter() { + fn _edits_details_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().details_get(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_details_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _edits_details_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AppDetails::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -856,60 +822,65 @@ impl Engine { request.default_language = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["contact-email", "contact-phone", "contact-website", "default-language"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.edits().details_patch(request, &self.opt.arg_package_name, &self.opt.arg_edit_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.edits().details_patch(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_details_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _edits_details_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AppDetails::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -937,554 +908,580 @@ impl Engine { request.default_language = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["contact-email", "contact-phone", "contact-website", "default-language"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.edits().details_update(request, &self.opt.arg_package_name, &self.opt.arg_edit_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.edits().details_update(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _edits_expansionfiles_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let apk_version_code: i32 = arg_from_str(&self.opt.arg_apk_version_code, err, "", "integer"); - let mut call = self.hub.edits().expansionfiles_get(&self.opt.arg_package_name, &self.opt.arg_edit_id, apk_version_code, &self.opt.arg_expansion_file_type); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _edits_expansionfiles_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - - let mut request = api::ExpansionFile::default(); - let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { - let last_errc = err.issues.len(); - let (key, value) = parse_kv_arg(&*kvarg, err, false); - let mut temp_cursor = field_cursor.clone(); - if let Err(field_err) = temp_cursor.set(&*key) { - err.issues.push(field_err); - } - if value.is_none() { - field_cursor = temp_cursor.clone(); - if err.issues.len() > last_errc { - err.issues.remove(last_errc); - } - continue; - } - match &temp_cursor.to_string()[..] { - "references-version" => { - request.references_version = Some(arg_from_str(value.unwrap_or("-0"), err, "references-version", "integer")); - }, - "file-size" => { - request.file_size = Some(value.unwrap_or("").to_string()); - }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } } } } - let apk_version_code: i32 = arg_from_str(&self.opt.arg_apk_version_code, err, "", "integer"); - let mut call = self.hub.edits().expansionfiles_patch(request, &self.opt.arg_package_name, &self.opt.arg_edit_id, apk_version_code, &self.opt.arg_expansion_file_type); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _edits_expansionfiles_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - - let mut request = api::ExpansionFile::default(); - let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { - let last_errc = err.issues.len(); - let (key, value) = parse_kv_arg(&*kvarg, err, false); - let mut temp_cursor = field_cursor.clone(); - if let Err(field_err) = temp_cursor.set(&*key) { - err.issues.push(field_err); - } - if value.is_none() { - field_cursor = temp_cursor.clone(); - if err.issues.len() > last_errc { - err.issues.remove(last_errc); - } - continue; - } - match &temp_cursor.to_string()[..] { - "references-version" => { - request.references_version = Some(arg_from_str(value.unwrap_or("-0"), err, "references-version", "integer")); - }, - "file-size" => { - request.file_size = Some(value.unwrap_or("").to_string()); - }, - _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); - } - } - } - let apk_version_code: i32 = arg_from_str(&self.opt.arg_apk_version_code, err, "", "integer"); - let mut call = self.hub.edits().expansionfiles_update(request, &self.opt.arg_package_name, &self.opt.arg_edit_id, apk_version_code, &self.opt.arg_expansion_file_type); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _edits_expansionfiles_upload(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let apk_version_code: i32 = arg_from_str(&self.opt.arg_apk_version_code, err, "", "integer"); - let mut call = self.hub.edits().expansionfiles_upload(&self.opt.arg_package_name, &self.opt.arg_edit_id, apk_version_code, &self.opt.arg_expansion_file_type); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().get(&self.opt.arg_package_name, &self.opt.arg_edit_id); - for parg in self.opt.arg_v.iter() { + fn _edits_expansionfiles_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let apk_version_code: i32 = arg_from_str(&opt.value_of("apk-version-code").unwrap_or(""), err, "", "integer"); + let mut call = self.hub.edits().expansionfiles_get(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), apk_version_code, opt.value_of("expansion-file-type").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_images_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().images_delete(&self.opt.arg_package_name, &self.opt.arg_edit_id, &self.opt.arg_language, &self.opt.arg_image_type, &self.opt.arg_image_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + fn _edits_expansionfiles_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::ExpansionFile::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "references-version" => { + request.references_version = Some(arg_from_str(value.unwrap_or("-0"), err, "references-version", "integer")); + }, + "file-size" => { + request.file_size = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["file-size", "references-version"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } } } - let protocol = "standard-request"; + let apk_version_code: i32 = arg_from_str(&opt.value_of("apk-version-code").unwrap_or(""), err, "", "integer"); + let mut call = self.hub.edits().expansionfiles_patch(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), apk_version_code, opt.value_of("expansion-file-type").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _edits_expansionfiles_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::ExpansionFile::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "references-version" => { + request.references_version = Some(arg_from_str(value.unwrap_or("-0"), err, "references-version", "integer")); + }, + "file-size" => { + request.file_size = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["file-size", "references-version"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let apk_version_code: i32 = arg_from_str(&opt.value_of("apk-version-code").unwrap_or(""), err, "", "integer"); + let mut call = self.hub.edits().expansionfiles_update(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), apk_version_code, opt.value_of("expansion-file-type").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _edits_expansionfiles_upload(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let apk_version_code: i32 = arg_from_str(&opt.value_of("apk-version-code").unwrap_or(""), err, "", "integer"); + let mut call = self.hub.edits().expansionfiles_upload(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), apk_version_code, opt.value_of("expansion-file-type").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _edits_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().get(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _edits_images_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().images_delete(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), opt.value_of("language").unwrap_or(""), opt.value_of("image-type").unwrap_or(""), opt.value_of("image-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _edits_images_deleteall(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().images_deleteall(&self.opt.arg_package_name, &self.opt.arg_edit_id, &self.opt.arg_language, &self.opt.arg_image_type); - for parg in self.opt.arg_v.iter() { + fn _edits_images_deleteall(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().images_deleteall(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), opt.value_of("language").unwrap_or(""), opt.value_of("image-type").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _edits_images_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().images_list(&self.opt.arg_package_name, &self.opt.arg_edit_id, &self.opt.arg_language, &self.opt.arg_image_type); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _edits_images_upload(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().images_upload(&self.opt.arg_package_name, &self.opt.arg_edit_id, &self.opt.arg_language, &self.opt.arg_image_type); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _edits_images_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().images_list(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), opt.value_of("language").unwrap_or(""), opt.value_of("image-type").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _edits_images_upload(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().images_upload(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), opt.value_of("language").unwrap_or(""), opt.value_of("image-type").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _edits_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AppEdit::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1506,240 +1503,251 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["expiry-time-seconds", "id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.edits().insert(request, &self.opt.arg_package_name); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.edits().insert(request, opt.value_of("package-name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_listings_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().listings_delete(&self.opt.arg_package_name, &self.opt.arg_edit_id, &self.opt.arg_language); - for parg in self.opt.arg_v.iter() { + fn _edits_listings_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().listings_delete(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), opt.value_of("language").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _edits_listings_deleteall(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().listings_deleteall(&self.opt.arg_package_name, &self.opt.arg_edit_id); - for parg in self.opt.arg_v.iter() { + fn _edits_listings_deleteall(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().listings_deleteall(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _edits_listings_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().listings_get(&self.opt.arg_package_name, &self.opt.arg_edit_id, &self.opt.arg_language); - for parg in self.opt.arg_v.iter() { + fn _edits_listings_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().listings_get(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), opt.value_of("language").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_listings_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().listings_list(&self.opt.arg_package_name, &self.opt.arg_edit_id); - for parg in self.opt.arg_v.iter() { + fn _edits_listings_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().listings_list(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_listings_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _edits_listings_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Listing::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1770,60 +1778,65 @@ impl Engine { request.title = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["full-description", "language", "short-description", "title", "video"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.edits().listings_patch(request, &self.opt.arg_package_name, &self.opt.arg_edit_id, &self.opt.arg_language); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.edits().listings_patch(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), opt.value_of("language").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_listings_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _edits_listings_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Listing::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1854,106 +1867,115 @@ impl Engine { request.title = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["full-description", "language", "short-description", "title", "video"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.edits().listings_update(request, &self.opt.arg_package_name, &self.opt.arg_edit_id, &self.opt.arg_language); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.edits().listings_update(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), opt.value_of("language").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_testers_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().testers_get(&self.opt.arg_package_name, &self.opt.arg_edit_id, &self.opt.arg_track); - for parg in self.opt.arg_v.iter() { + fn _edits_testers_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().testers_get(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), opt.value_of("track").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_testers_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _edits_testers_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Testers::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1981,60 +2003,65 @@ impl Engine { request.google_plus_communities.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["google-groups", "google-plus-communities"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.edits().testers_patch(request, &self.opt.arg_package_name, &self.opt.arg_edit_id, &self.opt.arg_track); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.edits().testers_patch(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), opt.value_of("track").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_testers_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _edits_testers_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Testers::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2062,152 +2089,165 @@ impl Engine { request.google_plus_communities.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["google-groups", "google-plus-communities"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.edits().testers_update(request, &self.opt.arg_package_name, &self.opt.arg_edit_id, &self.opt.arg_track); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.edits().testers_update(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), opt.value_of("track").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_tracks_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().tracks_get(&self.opt.arg_package_name, &self.opt.arg_edit_id, &self.opt.arg_track); - for parg in self.opt.arg_v.iter() { + fn _edits_tracks_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().tracks_get(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), opt.value_of("track").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_tracks_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().tracks_list(&self.opt.arg_package_name, &self.opt.arg_edit_id); - for parg in self.opt.arg_v.iter() { + fn _edits_tracks_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().tracks_list(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_tracks_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _edits_tracks_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Track::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2235,60 +2275,65 @@ impl Engine { request.version_codes.as_mut().unwrap().push(arg_from_str(value.unwrap_or("-0"), err, "version-codes", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["track", "user-fraction", "version-codes"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.edits().tracks_patch(request, &self.opt.arg_package_name, &self.opt.arg_edit_id, &self.opt.arg_track); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.edits().tracks_patch(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), opt.value_of("track").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_tracks_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _edits_tracks_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Track::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2316,106 +2361,115 @@ impl Engine { request.version_codes.as_mut().unwrap().push(arg_from_str(value.unwrap_or("-0"), err, "version-codes", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["track", "user-fraction", "version-codes"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.edits().tracks_update(request, &self.opt.arg_package_name, &self.opt.arg_edit_id, &self.opt.arg_track); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.edits().tracks_update(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or(""), opt.value_of("track").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _edits_validate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.edits().validate(&self.opt.arg_package_name, &self.opt.arg_edit_id); - for parg in self.opt.arg_v.iter() { + fn _edits_validate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.edits().validate(opt.value_of("package-name").unwrap_or(""), opt.value_of("edit-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _inappproducts_batch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _inappproducts_batch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InappproductsBatchRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2431,150 +2485,158 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.inappproducts().batch(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _inappproducts_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.inappproducts().delete(&self.opt.arg_package_name, &self.opt.arg_sku); - for parg in self.opt.arg_v.iter() { + fn _inappproducts_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.inappproducts().delete(opt.value_of("package-name").unwrap_or(""), opt.value_of("sku").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _inappproducts_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.inappproducts().get(&self.opt.arg_package_name, &self.opt.arg_sku); - for parg in self.opt.arg_v.iter() { + fn _inappproducts_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.inappproducts().get(opt.value_of("package-name").unwrap_or(""), opt.value_of("sku").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _inappproducts_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _inappproducts_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InAppProduct::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2665,61 +2727,66 @@ impl Engine { request.default_price.as_mut().unwrap().price_micros = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["currency", "day", "default-language", "default-price", "end", "month", "package-name", "price-micros", "purchase-type", "season", "sku", "start", "status", "subscription-period", "trial-period"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.inappproducts().insert(request, &self.opt.arg_package_name); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.inappproducts().insert(request, opt.value_of("package-name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "auto-convert-missing-prices" => { call = call.auto_convert_missing_prices(arg_from_str(value.unwrap_or("false"), err, "auto-convert-missing-prices", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["auto-convert-missing-prices"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _inappproducts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.inappproducts().list(&self.opt.arg_package_name); - for parg in self.opt.arg_v.iter() { + fn _inappproducts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.inappproducts().list(opt.value_of("package-name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "token" => { @@ -2731,52 +2798,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["token", "start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _inappproducts_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _inappproducts_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InAppProduct::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2867,63 +2938,68 @@ impl Engine { request.default_price.as_mut().unwrap().price_micros = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["currency", "day", "default-language", "default-price", "end", "month", "package-name", "price-micros", "purchase-type", "season", "sku", "start", "status", "subscription-period", "trial-period"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.inappproducts().patch(request, &self.opt.arg_package_name, &self.opt.arg_sku); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.inappproducts().patch(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("sku").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "auto-convert-missing-prices" => { call = call.auto_convert_missing_prices(arg_from_str(value.unwrap_or("false"), err, "auto-convert-missing-prices", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["auto-convert-missing-prices"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _inappproducts_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _inappproducts_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InAppProduct::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3014,153 +3090,161 @@ impl Engine { request.default_price.as_mut().unwrap().price_micros = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["currency", "day", "default-language", "default-price", "end", "month", "package-name", "price-micros", "purchase-type", "season", "sku", "start", "status", "subscription-period", "trial-period"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.inappproducts().update(request, &self.opt.arg_package_name, &self.opt.arg_sku); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.inappproducts().update(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("sku").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "auto-convert-missing-prices" => { call = call.auto_convert_missing_prices(arg_from_str(value.unwrap_or("false"), err, "auto-convert-missing-prices", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["auto-convert-missing-prices"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _purchases_products_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.purchases().products_get(&self.opt.arg_package_name, &self.opt.arg_product_id, &self.opt.arg_token); - for parg in self.opt.arg_v.iter() { + fn _purchases_products_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.purchases().products_get(opt.value_of("package-name").unwrap_or(""), opt.value_of("product-id").unwrap_or(""), opt.value_of("token").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _purchases_subscriptions_cancel(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.purchases().subscriptions_cancel(&self.opt.arg_package_name, &self.opt.arg_subscription_id, &self.opt.arg_token); - for parg in self.opt.arg_v.iter() { + fn _purchases_subscriptions_cancel(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.purchases().subscriptions_cancel(opt.value_of("package-name").unwrap_or(""), opt.value_of("subscription-id").unwrap_or(""), opt.value_of("token").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _purchases_subscriptions_defer(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _purchases_subscriptions_defer(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SubscriptionPurchasesDeferRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3190,325 +3274,397 @@ impl Engine { request.deferral_info.as_mut().unwrap().desired_expiry_time_millis = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["deferral-info", "desired-expiry-time-millis", "expected-expiry-time-millis"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.purchases().subscriptions_defer(request, &self.opt.arg_package_name, &self.opt.arg_subscription_id, &self.opt.arg_token); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.purchases().subscriptions_defer(request, opt.value_of("package-name").unwrap_or(""), opt.value_of("subscription-id").unwrap_or(""), opt.value_of("token").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _purchases_subscriptions_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.purchases().subscriptions_get(&self.opt.arg_package_name, &self.opt.arg_subscription_id, &self.opt.arg_token); - for parg in self.opt.arg_v.iter() { + fn _purchases_subscriptions_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.purchases().subscriptions_get(opt.value_of("package-name").unwrap_or(""), opt.value_of("subscription-id").unwrap_or(""), opt.value_of("token").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _purchases_subscriptions_refund(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.purchases().subscriptions_refund(&self.opt.arg_package_name, &self.opt.arg_subscription_id, &self.opt.arg_token); - for parg in self.opt.arg_v.iter() { + fn _purchases_subscriptions_refund(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.purchases().subscriptions_refund(opt.value_of("package-name").unwrap_or(""), opt.value_of("subscription-id").unwrap_or(""), opt.value_of("token").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _purchases_subscriptions_revoke(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.purchases().subscriptions_revoke(&self.opt.arg_package_name, &self.opt.arg_subscription_id, &self.opt.arg_token); - for parg in self.opt.arg_v.iter() { + fn _purchases_subscriptions_revoke(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.purchases().subscriptions_revoke(opt.value_of("package-name").unwrap_or(""), opt.value_of("subscription-id").unwrap_or(""), opt.value_of("token").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_edits { - if self.opt.cmd_apklistings_delete { - call_result = self._edits_apklistings_delete(dry_run, &mut err); - } else if self.opt.cmd_apklistings_deleteall { - call_result = self._edits_apklistings_deleteall(dry_run, &mut err); - } else if self.opt.cmd_apklistings_get { - call_result = self._edits_apklistings_get(dry_run, &mut err); - } else if self.opt.cmd_apklistings_list { - call_result = self._edits_apklistings_list(dry_run, &mut err); - } else if self.opt.cmd_apklistings_patch { - call_result = self._edits_apklistings_patch(dry_run, &mut err); - } else if self.opt.cmd_apklistings_update { - call_result = self._edits_apklistings_update(dry_run, &mut err); - } else if self.opt.cmd_apks_addexternallyhosted { - call_result = self._edits_apks_addexternallyhosted(dry_run, &mut err); - } else if self.opt.cmd_apks_list { - call_result = self._edits_apks_list(dry_run, &mut err); - } else if self.opt.cmd_apks_upload { - call_result = self._edits_apks_upload(dry_run, &mut err); - } else if self.opt.cmd_commit { - call_result = self._edits_commit(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._edits_delete(dry_run, &mut err); - } else if self.opt.cmd_details_get { - call_result = self._edits_details_get(dry_run, &mut err); - } else if self.opt.cmd_details_patch { - call_result = self._edits_details_patch(dry_run, &mut err); - } else if self.opt.cmd_details_update { - call_result = self._edits_details_update(dry_run, &mut err); - } else if self.opt.cmd_expansionfiles_get { - call_result = self._edits_expansionfiles_get(dry_run, &mut err); - } else if self.opt.cmd_expansionfiles_patch { - call_result = self._edits_expansionfiles_patch(dry_run, &mut err); - } else if self.opt.cmd_expansionfiles_update { - call_result = self._edits_expansionfiles_update(dry_run, &mut err); - } else if self.opt.cmd_expansionfiles_upload { - call_result = self._edits_expansionfiles_upload(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._edits_get(dry_run, &mut err); - } else if self.opt.cmd_images_delete { - call_result = self._edits_images_delete(dry_run, &mut err); - } else if self.opt.cmd_images_deleteall { - call_result = self._edits_images_deleteall(dry_run, &mut err); - } else if self.opt.cmd_images_list { - call_result = self._edits_images_list(dry_run, &mut err); - } else if self.opt.cmd_images_upload { - call_result = self._edits_images_upload(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._edits_insert(dry_run, &mut err); - } else if self.opt.cmd_listings_delete { - call_result = self._edits_listings_delete(dry_run, &mut err); - } else if self.opt.cmd_listings_deleteall { - call_result = self._edits_listings_deleteall(dry_run, &mut err); - } else if self.opt.cmd_listings_get { - call_result = self._edits_listings_get(dry_run, &mut err); - } else if self.opt.cmd_listings_list { - call_result = self._edits_listings_list(dry_run, &mut err); - } else if self.opt.cmd_listings_patch { - call_result = self._edits_listings_patch(dry_run, &mut err); - } else if self.opt.cmd_listings_update { - call_result = self._edits_listings_update(dry_run, &mut err); - } else if self.opt.cmd_testers_get { - call_result = self._edits_testers_get(dry_run, &mut err); - } else if self.opt.cmd_testers_patch { - call_result = self._edits_testers_patch(dry_run, &mut err); - } else if self.opt.cmd_testers_update { - call_result = self._edits_testers_update(dry_run, &mut err); - } else if self.opt.cmd_tracks_get { - call_result = self._edits_tracks_get(dry_run, &mut err); - } else if self.opt.cmd_tracks_list { - call_result = self._edits_tracks_list(dry_run, &mut err); - } else if self.opt.cmd_tracks_patch { - call_result = self._edits_tracks_patch(dry_run, &mut err); - } else if self.opt.cmd_tracks_update { - call_result = self._edits_tracks_update(dry_run, &mut err); - } else if self.opt.cmd_validate { - call_result = self._edits_validate(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("edits", Some(opt)) => { + match opt.subcommand() { + ("apklistings-delete", Some(opt)) => { + call_result = self._edits_apklistings_delete(opt, dry_run, &mut err); + }, + ("apklistings-deleteall", Some(opt)) => { + call_result = self._edits_apklistings_deleteall(opt, dry_run, &mut err); + }, + ("apklistings-get", Some(opt)) => { + call_result = self._edits_apklistings_get(opt, dry_run, &mut err); + }, + ("apklistings-list", Some(opt)) => { + call_result = self._edits_apklistings_list(opt, dry_run, &mut err); + }, + ("apklistings-patch", Some(opt)) => { + call_result = self._edits_apklistings_patch(opt, dry_run, &mut err); + }, + ("apklistings-update", Some(opt)) => { + call_result = self._edits_apklistings_update(opt, dry_run, &mut err); + }, + ("apks-addexternallyhosted", Some(opt)) => { + call_result = self._edits_apks_addexternallyhosted(opt, dry_run, &mut err); + }, + ("apks-list", Some(opt)) => { + call_result = self._edits_apks_list(opt, dry_run, &mut err); + }, + ("apks-upload", Some(opt)) => { + call_result = self._edits_apks_upload(opt, dry_run, &mut err); + }, + ("commit", Some(opt)) => { + call_result = self._edits_commit(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._edits_delete(opt, dry_run, &mut err); + }, + ("details-get", Some(opt)) => { + call_result = self._edits_details_get(opt, dry_run, &mut err); + }, + ("details-patch", Some(opt)) => { + call_result = self._edits_details_patch(opt, dry_run, &mut err); + }, + ("details-update", Some(opt)) => { + call_result = self._edits_details_update(opt, dry_run, &mut err); + }, + ("expansionfiles-get", Some(opt)) => { + call_result = self._edits_expansionfiles_get(opt, dry_run, &mut err); + }, + ("expansionfiles-patch", Some(opt)) => { + call_result = self._edits_expansionfiles_patch(opt, dry_run, &mut err); + }, + ("expansionfiles-update", Some(opt)) => { + call_result = self._edits_expansionfiles_update(opt, dry_run, &mut err); + }, + ("expansionfiles-upload", Some(opt)) => { + call_result = self._edits_expansionfiles_upload(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._edits_get(opt, dry_run, &mut err); + }, + ("images-delete", Some(opt)) => { + call_result = self._edits_images_delete(opt, dry_run, &mut err); + }, + ("images-deleteall", Some(opt)) => { + call_result = self._edits_images_deleteall(opt, dry_run, &mut err); + }, + ("images-list", Some(opt)) => { + call_result = self._edits_images_list(opt, dry_run, &mut err); + }, + ("images-upload", Some(opt)) => { + call_result = self._edits_images_upload(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._edits_insert(opt, dry_run, &mut err); + }, + ("listings-delete", Some(opt)) => { + call_result = self._edits_listings_delete(opt, dry_run, &mut err); + }, + ("listings-deleteall", Some(opt)) => { + call_result = self._edits_listings_deleteall(opt, dry_run, &mut err); + }, + ("listings-get", Some(opt)) => { + call_result = self._edits_listings_get(opt, dry_run, &mut err); + }, + ("listings-list", Some(opt)) => { + call_result = self._edits_listings_list(opt, dry_run, &mut err); + }, + ("listings-patch", Some(opt)) => { + call_result = self._edits_listings_patch(opt, dry_run, &mut err); + }, + ("listings-update", Some(opt)) => { + call_result = self._edits_listings_update(opt, dry_run, &mut err); + }, + ("testers-get", Some(opt)) => { + call_result = self._edits_testers_get(opt, dry_run, &mut err); + }, + ("testers-patch", Some(opt)) => { + call_result = self._edits_testers_patch(opt, dry_run, &mut err); + }, + ("testers-update", Some(opt)) => { + call_result = self._edits_testers_update(opt, dry_run, &mut err); + }, + ("tracks-get", Some(opt)) => { + call_result = self._edits_tracks_get(opt, dry_run, &mut err); + }, + ("tracks-list", Some(opt)) => { + call_result = self._edits_tracks_list(opt, dry_run, &mut err); + }, + ("tracks-patch", Some(opt)) => { + call_result = self._edits_tracks_patch(opt, dry_run, &mut err); + }, + ("tracks-update", Some(opt)) => { + call_result = self._edits_tracks_update(opt, dry_run, &mut err); + }, + ("validate", Some(opt)) => { + call_result = self._edits_validate(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("edits".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("inappproducts", Some(opt)) => { + match opt.subcommand() { + ("batch", Some(opt)) => { + call_result = self._inappproducts_batch(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._inappproducts_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._inappproducts_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._inappproducts_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._inappproducts_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._inappproducts_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._inappproducts_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("inappproducts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("purchases", Some(opt)) => { + match opt.subcommand() { + ("products-get", Some(opt)) => { + call_result = self._purchases_products_get(opt, dry_run, &mut err); + }, + ("subscriptions-cancel", Some(opt)) => { + call_result = self._purchases_subscriptions_cancel(opt, dry_run, &mut err); + }, + ("subscriptions-defer", Some(opt)) => { + call_result = self._purchases_subscriptions_defer(opt, dry_run, &mut err); + }, + ("subscriptions-get", Some(opt)) => { + call_result = self._purchases_subscriptions_get(opt, dry_run, &mut err); + }, + ("subscriptions-refund", Some(opt)) => { + call_result = self._purchases_subscriptions_refund(opt, dry_run, &mut err); + }, + ("subscriptions-revoke", Some(opt)) => { + call_result = self._purchases_subscriptions_revoke(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("purchases".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_inappproducts { - if self.opt.cmd_batch { - call_result = self._inappproducts_batch(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._inappproducts_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._inappproducts_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._inappproducts_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._inappproducts_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._inappproducts_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._inappproducts_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_purchases { - if self.opt.cmd_products_get { - call_result = self._purchases_products_get(dry_run, &mut err); - } else if self.opt.cmd_subscriptions_cancel { - call_result = self._purchases_subscriptions_cancel(dry_run, &mut err); - } else if self.opt.cmd_subscriptions_defer { - call_result = self._purchases_subscriptions_defer(dry_run, &mut err); - } else if self.opt.cmd_subscriptions_get { - call_result = self._purchases_subscriptions_get(dry_run, &mut err); - } else if self.opt.cmd_subscriptions_refund { - call_result = self._purchases_subscriptions_refund(dry_run, &mut err); - } else if self.opt.cmd_subscriptions_revoke { - call_result = self._purchases_subscriptions_revoke(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -3521,7 +3677,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -3534,7 +3690,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -3544,37 +3700,1872 @@ impl Engine { let engine = Engine { opt: opt, hub: api::AndroidPublisher::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let upload_value_names = ["mode", "file"]; + let arg_data = [ + ("edits", "methods: 'apklistings-delete', 'apklistings-deleteall', 'apklistings-get', 'apklistings-list', 'apklistings-patch', 'apklistings-update', 'apks-addexternallyhosted', 'apks-list', 'apks-upload', 'commit', 'delete', 'details-get', 'details-patch', 'details-update', 'expansionfiles-get', 'expansionfiles-patch', 'expansionfiles-update', 'expansionfiles-upload', 'get', 'images-delete', 'images-deleteall', 'images-list', 'images-upload', 'insert', 'listings-delete', 'listings-deleteall', 'listings-get', 'listings-list', 'listings-patch', 'listings-update', 'testers-get', 'testers-patch', 'testers-update', 'tracks-get', 'tracks-list', 'tracks-patch', 'tracks-update' and 'validate'", vec![ + ("apklistings-delete", + Some(r##"Deletes the APK-specific localized listing for a specified APK and language code."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_apklistings-delete", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"apk-version-code"##), + None, + Some(r##"The APK version code whose APK-specific listings should be read or modified."##), + Some(true), + Some(false)), + + (Some(r##"language"##), + None, + Some(r##"The language code (a BCP-47 language tag) of the APK-specific localized listing to read or modify. For example, to select Austrian German, pass "de-AT"."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("apklistings-deleteall", + Some(r##"Deletes all the APK-specific localized listings for a specified APK."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_apklistings-deleteall", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"apk-version-code"##), + None, + Some(r##"The APK version code whose APK-specific listings should be read or modified."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("apklistings-get", + Some(r##"Fetches the APK-specific localized listing for a specified APK and language code."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_apklistings-get", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"apk-version-code"##), + None, + Some(r##"The APK version code whose APK-specific listings should be read or modified."##), + Some(true), + Some(false)), + + (Some(r##"language"##), + None, + Some(r##"The language code (a BCP-47 language tag) of the APK-specific localized listing to read or modify. For example, to select Austrian German, pass "de-AT"."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("apklistings-list", + Some(r##"Lists all the APK-specific localized listings for a specified APK."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_apklistings-list", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"apk-version-code"##), + None, + Some(r##"The APK version code whose APK-specific listings should be read or modified."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("apklistings-patch", + Some(r##"Updates or creates the APK-specific localized listing for a specified APK and language code. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_apklistings-patch", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"apk-version-code"##), + None, + Some(r##"The APK version code whose APK-specific listings should be read or modified."##), + Some(true), + Some(false)), + + (Some(r##"language"##), + None, + Some(r##"The language code (a BCP-47 language tag) of the APK-specific localized listing to read or modify. For example, to select Austrian German, pass "de-AT"."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("apklistings-update", + Some(r##"Updates or creates the APK-specific localized listing for a specified APK and language code."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_apklistings-update", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"apk-version-code"##), + None, + Some(r##"The APK version code whose APK-specific listings should be read or modified."##), + Some(true), + Some(false)), + + (Some(r##"language"##), + None, + Some(r##"The language code (a BCP-47 language tag) of the APK-specific localized listing to read or modify. For example, to select Austrian German, pass "de-AT"."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("apks-addexternallyhosted", + Some(r##"Creates a new APK without uploading the APK itself to Google Play, instead hosting the APK at a specified URL. This function is only available to enterprises using Google Play for Work whose application is configured to restrict distribution to the enterprise domain."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_apks-addexternallyhosted", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("apks-list", + None, + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_apks-list", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("apks-upload", + None, + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_apks-upload", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("commit", + Some(r##"Commits/applies the changes made in this edit back to the app."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_commit", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes an edit for an app. Creating a new edit will automatically delete any of your previous edits so this method need only be called if you want to preemptively abandon an edit."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_delete", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("details-get", + Some(r##"Fetches app details for this edit. This includes the default language and developer support contact information."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_details-get", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("details-patch", + Some(r##"Updates app details for this edit. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_details-patch", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("details-update", + Some(r##"Updates app details for this edit."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_details-update", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("expansionfiles-get", + Some(r##"Fetches the Expansion File configuration for the APK specified."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_expansionfiles-get", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"apk-version-code"##), + None, + Some(r##"The version code of the APK whose Expansion File configuration is being read or modified."##), + Some(true), + Some(false)), + + (Some(r##"expansion-file-type"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("expansionfiles-patch", + Some(r##"Updates the APK's Expansion File configuration to reference another APK's Expansion Files. To add a new Expansion File use the Upload method. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_expansionfiles-patch", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"apk-version-code"##), + None, + Some(r##"The version code of the APK whose Expansion File configuration is being read or modified."##), + Some(true), + Some(false)), + + (Some(r##"expansion-file-type"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("expansionfiles-update", + Some(r##"Updates the APK's Expansion File configuration to reference another APK's Expansion Files. To add a new Expansion File use the Upload method."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_expansionfiles-update", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"apk-version-code"##), + None, + Some(r##"The version code of the APK whose Expansion File configuration is being read or modified."##), + Some(true), + Some(false)), + + (Some(r##"expansion-file-type"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("expansionfiles-upload", + Some(r##"Uploads and attaches a new Expansion File to the APK specified."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_expansionfiles-upload", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"apk-version-code"##), + None, + Some(r##"The version code of the APK whose Expansion File configuration is being read or modified."##), + Some(true), + Some(false)), + + (Some(r##"expansion-file-type"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns information about the edit specified. Calls will fail if the edit is no long active (e.g. has been deleted, superseded or expired)."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_get", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("images-delete", + Some(r##"Deletes the image (specified by id) from the edit."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_images-delete", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"language"##), + None, + Some(r##"The language code (a BCP-47 language tag) of the localized listing whose images are to read or modified. For example, to select Austrian German, pass "de-AT"."##), + Some(true), + Some(false)), + + (Some(r##"image-type"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"image-id"##), + None, + Some(r##"Unique identifier an image within the set of images attached to this edit."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("images-deleteall", + Some(r##"Deletes all images for the specified language and image type."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_images-deleteall", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"language"##), + None, + Some(r##"The language code (a BCP-47 language tag) of the localized listing whose images are to read or modified. For example, to select Austrian German, pass "de-AT"."##), + Some(true), + Some(false)), + + (Some(r##"image-type"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("images-list", + Some(r##"Lists all images for the specified language and image type."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_images-list", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"language"##), + None, + Some(r##"The language code (a BCP-47 language tag) of the localized listing whose images are to read or modified. For example, to select Austrian German, pass "de-AT"."##), + Some(true), + Some(false)), + + (Some(r##"image-type"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("images-upload", + Some(r##"Uploads a new image and adds it to the list of images for the specified language and image type."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_images-upload", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"language"##), + None, + Some(r##"The language code (a BCP-47 language tag) of the localized listing whose images are to read or modified. For example, to select Austrian German, pass "de-AT"."##), + Some(true), + Some(false)), + + (Some(r##"image-type"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new edit for an app, populated with the app's current state."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_insert", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("listings-delete", + Some(r##"Deletes the specified localized store listing from an edit."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_listings-delete", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"language"##), + None, + Some(r##"The language code (a BCP-47 language tag) of the localized listing to read or modify. For example, to select Austrian German, pass "de-AT"."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("listings-deleteall", + Some(r##"Deletes all localized listings from an edit."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_listings-deleteall", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("listings-get", + Some(r##"Fetches information about a localized store listing."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_listings-get", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"language"##), + None, + Some(r##"The language code (a BCP-47 language tag) of the localized listing to read or modify. For example, to select Austrian German, pass "de-AT"."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("listings-list", + Some(r##"Returns all of the localized store listings attached to this edit."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_listings-list", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("listings-patch", + Some(r##"Creates or updates a localized store listing. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_listings-patch", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"language"##), + None, + Some(r##"The language code (a BCP-47 language tag) of the localized listing to read or modify. For example, to select Austrian German, pass "de-AT"."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("listings-update", + Some(r##"Creates or updates a localized store listing."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_listings-update", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"language"##), + None, + Some(r##"The language code (a BCP-47 language tag) of the localized listing to read or modify. For example, to select Austrian German, pass "de-AT"."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("testers-get", + None, + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_testers-get", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"track"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("testers-patch", + None, + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_testers-patch", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"track"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("testers-update", + None, + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_testers-update", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"track"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("tracks-get", + Some(r##"Fetches the track configuration for the specified track type. Includes the APK version codes that are in this track."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_tracks-get", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"track"##), + None, + Some(r##"The track type to read or modify."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("tracks-list", + Some(r##"Lists all the track configurations for this edit."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_tracks-list", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("tracks-patch", + Some(r##"Updates the track configuration for the specified track type. When halted, the rollout track cannot be updated without adding new APKs, and adding new APKs will cause it to resume. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_tracks-patch", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"track"##), + None, + Some(r##"The track type to read or modify."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("tracks-update", + Some(r##"Updates the track configuration for the specified track type. When halted, the rollout track cannot be updated without adding new APKs, and adding new APKs will cause it to resume."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_tracks-update", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"track"##), + None, + Some(r##"The track type to read or modify."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("validate", + Some(r##"Checks that the edit can be successfully committed. The edit's changes are not applied to the live app."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/edits_validate", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app that is being updated; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"edit-id"##), + None, + Some(r##"Unique identifier for this edit."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("inappproducts", "methods: 'batch', 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("batch", + None, + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/inappproducts_batch", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Delete an in-app product for an app."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/inappproducts_delete", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app with the in-app product; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"sku"##), + None, + Some(r##"Unique identifier for the in-app product."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Returns information about the in-app product specified."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/inappproducts_get", + vec![ + (Some(r##"package-name"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"sku"##), + None, + Some(r##"Unique identifier for the in-app product."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new in-app product for an app."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/inappproducts_insert", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all the in-app products for an Android app, both subscriptions and managed in-app products.."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/inappproducts_list", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app with in-app products; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates the details of an in-app product. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/inappproducts_patch", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app with the in-app product; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"sku"##), + None, + Some(r##"Unique identifier for the in-app product."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates the details of an in-app product."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/inappproducts_update", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"Unique identifier for the Android app with the in-app product; for example, "com.spiffygame"."##), + Some(true), + Some(false)), + + (Some(r##"sku"##), + None, + Some(r##"Unique identifier for the in-app product."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("purchases", "methods: 'products-get', 'subscriptions-cancel', 'subscriptions-defer', 'subscriptions-get', 'subscriptions-refund' and 'subscriptions-revoke'", vec![ + ("products-get", + Some(r##"Checks the purchase and consumption status of an inapp item."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/purchases_products-get", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"The package name of the application the inapp product was sold in (for example, 'com.some.thing')."##), + Some(true), + Some(false)), + + (Some(r##"product-id"##), + None, + Some(r##"The inapp product SKU (for example, 'com.some.thing.inapp1')."##), + Some(true), + Some(false)), + + (Some(r##"token"##), + None, + Some(r##"The token provided to the user's device when the inapp product was purchased."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("subscriptions-cancel", + Some(r##"Cancels a user's subscription purchase. The subscription remains valid until its expiration time."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/purchases_subscriptions-cancel", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"The package name of the application for which this subscription was purchased (for example, 'com.some.thing')."##), + Some(true), + Some(false)), + + (Some(r##"subscription-id"##), + None, + Some(r##"The purchased subscription ID (for example, 'monthly001')."##), + Some(true), + Some(false)), + + (Some(r##"token"##), + None, + Some(r##"The token provided to the user's device when the subscription was purchased."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("subscriptions-defer", + Some(r##"Defers a user's subscription purchase until a specified future expiration time."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/purchases_subscriptions-defer", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"The package name of the application for which this subscription was purchased (for example, 'com.some.thing')."##), + Some(true), + Some(false)), + + (Some(r##"subscription-id"##), + None, + Some(r##"The purchased subscription ID (for example, 'monthly001')."##), + Some(true), + Some(false)), + + (Some(r##"token"##), + None, + Some(r##"The token provided to the user's device when the subscription was purchased."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("subscriptions-get", + Some(r##"Checks whether a user's subscription purchase is valid and returns its expiry time."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/purchases_subscriptions-get", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"The package name of the application for which this subscription was purchased (for example, 'com.some.thing')."##), + Some(true), + Some(false)), + + (Some(r##"subscription-id"##), + None, + Some(r##"The purchased subscription ID (for example, 'monthly001')."##), + Some(true), + Some(false)), + + (Some(r##"token"##), + None, + Some(r##"The token provided to the user's device when the subscription was purchased."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("subscriptions-refund", + Some(r##"Refunds a user's subscription purchase, but the subscription remains valid until its expiration time and it will continue to recur."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/purchases_subscriptions-refund", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"The package name of the application for which this subscription was purchased (for example, 'com.some.thing')."##), + Some(true), + Some(false)), + + (Some(r##"subscription-id"##), + None, + Some(r##"The purchased subscription ID (for example, 'monthly001')."##), + Some(true), + Some(false)), + + (Some(r##"token"##), + None, + Some(r##"The token provided to the user's device when the subscription was purchased."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("subscriptions-revoke", + Some(r##"Refunds and immediately revokes a user's subscription purchase. Access to the subscription will be terminated immediately and it will stop recurring."##), + "Details at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli/purchases_subscriptions-revoke", + vec![ + (Some(r##"package-name"##), + None, + Some(r##"The package name of the application for which this subscription was purchased (for example, 'com.some.thing')."##), + Some(true), + Some(false)), + + (Some(r##"subscription-id"##), + None, + Some(r##"The purchased subscription ID (for example, 'monthly001')."##), + Some(true), + Some(false)), + + (Some(r##"token"##), + None, + Some(r##"The token provided to the user's device when the subscription was purchased."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ]; + + let mut app = App::new("androidpublisher2") + .author("Sebastian Thiel ") + .version("0.2.0+20150323") + .about("Lets Android application developers access their Google Play accounts.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_androidpublisher2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + if arg_name_str == "mode" { + arg = arg.number_of_values(2); + arg = arg.value_names(&upload_value_names); + + scmd = scmd.arg(Arg::with_name("mime") + .short("m") + .requires("mode") + .required(false) + .help("The file's mime time, like 'application/octet-stream'") + .takes_value(true)); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/androidpublisher2/Cargo.toml b/gen/androidpublisher2/Cargo.toml index 2a7fbe3064..6b40ab664a 100644 --- a/gen/androidpublisher2/Cargo.toml +++ b/gen/androidpublisher2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-androidpublisher2" -version = "0.1.6+20150323" +version = "0.1.7+20150323" authors = ["Sebastian Thiel "] description = "A complete library to interact with Android Publisher (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/androidpublisher2" @@ -15,9 +15,10 @@ keywords = ["androidpublisher", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/androidpublisher2/README.md b/gen/androidpublisher2/README.md index d44eb2dbcb..abea5b7926 100644 --- a/gen/androidpublisher2/README.md +++ b/gen/androidpublisher2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-androidpublisher2` library allows access to all features of the *Google Android Publisher* service. -This documentation was generated from *Android Publisher* crate version *0.1.6+20150323*, where *20150323* is the exact revision of the *androidpublisher:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *Android Publisher* crate version *0.1.7+20150323*, where *20150323* is the exact revision of the *androidpublisher:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *Android Publisher* *v2* API can be found at the [official documentation site](https://developers.google.com/android-publisher). @@ -177,7 +177,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_androidpublisher2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_androidpublisher2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/androidpublisher2/src/cmn.rs b/gen/androidpublisher2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/androidpublisher2/src/cmn.rs +++ b/gen/androidpublisher2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/androidpublisher2/src/lib.rs b/gen/androidpublisher2/src/lib.rs index 895314c563..b11f08ad9e 100644 --- a/gen/androidpublisher2/src/lib.rs +++ b/gen/androidpublisher2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *Android Publisher* crate version *0.1.6+20150323*, where *20150323* is the exact revision of the *androidpublisher:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *Android Publisher* crate version *0.1.7+20150323*, where *20150323* is the exact revision of the *androidpublisher:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *Android Publisher* *v2* API can be found at the //! [official documentation site](https://developers.google.com/android-publisher). @@ -178,7 +178,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -187,7 +187,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -203,6 +202,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -326,7 +326,7 @@ impl<'a, C, A> AndroidPublisher AndroidPublisher { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -341,7 +341,7 @@ impl<'a, C, A> AndroidPublisher } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -2585,7 +2585,7 @@ impl<'a, C, A> PurchaseSubscriptionRevokeCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2607,7 +2607,7 @@ impl<'a, C, A> PurchaseSubscriptionRevokeCall<'a, C, A> where C: BorrowMut PurchaseProductGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2860,7 +2860,7 @@ impl<'a, C, A> PurchaseProductGetCall<'a, C, A> where C: BorrowMut PurchaseSubscriptionGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3123,7 +3123,7 @@ impl<'a, C, A> PurchaseSubscriptionGetCall<'a, C, A> where C: BorrowMut PurchaseSubscriptionCancelCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3385,7 +3385,7 @@ impl<'a, C, A> PurchaseSubscriptionCancelCall<'a, C, A> where C: BorrowMut PurchaseSubscriptionRefundCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3637,7 +3637,7 @@ impl<'a, C, A> PurchaseSubscriptionRefundCall<'a, C, A> where C: BorrowMut PurchaseSubscriptionDeferCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, SubscriptionPurchasesDeferResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3875,11 +3876,20 @@ impl<'a, C, A> PurchaseSubscriptionDeferCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3902,7 +3912,7 @@ impl<'a, C, A> PurchaseSubscriptionDeferCall<'a, C, A> where C: BorrowMut EditImageUploadCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4205,7 +4215,7 @@ impl<'a, C, A> EditImageUploadCall<'a, C, A> where C: BorrowMut, response } else { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); if protocol == "simple" { @@ -4263,7 +4273,7 @@ impl<'a, C, A> EditImageUploadCall<'a, C, A> where C: BorrowMut, let upload_result = { let url_str = &res.headers.get::().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -4291,6 +4301,7 @@ impl<'a, C, A> EditImageUploadCall<'a, C, A> where C: BorrowMut, Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -4491,6 +4502,7 @@ impl<'a, C, A> EditExpansionfileUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, ExpansionFile)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4549,11 +4561,20 @@ impl<'a, C, A> EditExpansionfileUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4576,7 +4597,7 @@ impl<'a, C, A> EditExpansionfileUpdateCall<'a, C, A> where C: BorrowMut EditDetailGetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4858,7 +4879,7 @@ impl<'a, C, A> EditDetailGetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5090,7 +5111,7 @@ impl<'a, C, A> EditApklistingDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5112,7 +5133,7 @@ impl<'a, C, A> EditApklistingDeleteCall<'a, C, A> where C: BorrowMut EditListingDeleteallCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5372,7 +5393,7 @@ impl<'a, C, A> EditListingDeleteallCall<'a, C, A> where C: BorrowMut EditApkAddexternallyhostedCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, ApksAddExternallyHostedResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5598,11 +5620,20 @@ impl<'a, C, A> EditApkAddexternallyhostedCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5625,7 +5656,7 @@ impl<'a, C, A> EditApkAddexternallyhostedCall<'a, C, A> where C: BorrowMut EditApklistingDeleteallCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5889,7 +5920,7 @@ impl<'a, C, A> EditApklistingDeleteallCall<'a, C, A> where C: BorrowMut EditDetailUpdateCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AppDetails)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6125,11 +6157,20 @@ impl<'a, C, A> EditDetailUpdateCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6152,7 +6193,7 @@ impl<'a, C, A> EditDetailUpdateCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6395,7 +6436,7 @@ impl<'a, C, A> EditTrackGetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6417,7 +6458,7 @@ impl<'a, C, A> EditTrackGetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6609,6 +6650,7 @@ impl<'a, C, A> EditExpansionfilePatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, ExpansionFile)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6667,11 +6709,20 @@ impl<'a, C, A> EditExpansionfilePatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6694,7 +6745,7 @@ impl<'a, C, A> EditExpansionfilePatchCall<'a, C, A> where C: BorrowMut EditImageListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6980,7 +7031,7 @@ impl<'a, C, A> EditImageListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7180,6 +7231,7 @@ impl<'a, C, A> EditTrackUpdateCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Track)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7237,11 +7289,20 @@ impl<'a, C, A> EditTrackUpdateCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7264,7 +7325,7 @@ impl<'a, C, A> EditTrackUpdateCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7467,6 +7528,7 @@ impl<'a, C, A> EditListingPatchCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Listing)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7524,11 +7586,20 @@ impl<'a, C, A> EditListingPatchCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7551,7 +7622,7 @@ impl<'a, C, A> EditListingPatchCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7802,7 +7873,7 @@ impl<'a, C, A> EditGetCall<'a, C, A> where C: BorrowMut, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7824,7 +7895,7 @@ impl<'a, C, A> EditGetCall<'a, C, A> where C: BorrowMut, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8058,7 +8129,7 @@ impl<'a, C, A> EditImageDeleteCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8080,7 +8151,7 @@ impl<'a, C, A> EditImageDeleteCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8336,7 +8407,7 @@ impl<'a, C, A> EditApkUploadCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8374,7 +8445,7 @@ impl<'a, C, A> EditApkUploadCall<'a, C, A> where C: BorrowMut, A: response } else { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); if protocol == "simple" { @@ -8432,7 +8503,7 @@ impl<'a, C, A> EditApkUploadCall<'a, C, A> where C: BorrowMut, A: let upload_result = { let url_str = &res.headers.get::().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -8460,6 +8531,7 @@ impl<'a, C, A> EditApkUploadCall<'a, C, A> where C: BorrowMut, A: Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -8641,6 +8713,7 @@ impl<'a, C, A> EditApklistingUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, ApkListing)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8699,11 +8772,20 @@ impl<'a, C, A> EditApklistingUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8726,7 +8808,7 @@ impl<'a, C, A> EditApklistingUpdateCall<'a, C, A> where C: BorrowMut EditApkListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9007,7 +9089,7 @@ impl<'a, C, A> EditApkListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9189,6 +9271,7 @@ impl<'a, C, A> EditApklistingPatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, ApkListing)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9247,11 +9330,20 @@ impl<'a, C, A> EditApklistingPatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9274,7 +9366,7 @@ impl<'a, C, A> EditApklistingPatchCall<'a, C, A> where C: BorrowMut EditListingGetCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9559,7 +9651,7 @@ impl<'a, C, A> EditListingGetCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9798,7 +9890,7 @@ impl<'a, C, A> EditTesterGetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9820,7 +9912,7 @@ impl<'a, C, A> EditTesterGetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10057,7 +10149,7 @@ impl<'a, C, A> EditDeleteCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10079,7 +10171,7 @@ impl<'a, C, A> EditDeleteCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10312,7 +10404,7 @@ impl<'a, C, A> EditExpansionfileUploadCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10350,7 +10442,7 @@ impl<'a, C, A> EditExpansionfileUploadCall<'a, C, A> where C: BorrowMut EditExpansionfileUploadCall<'a, C, A> where C: BorrowMut().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -10436,6 +10528,7 @@ impl<'a, C, A> EditExpansionfileUploadCall<'a, C, A> where C: BorrowMut { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -10633,6 +10726,7 @@ impl<'a, C, A> EditInsertCall<'a, C, A> where C: BorrowMut, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AppEdit)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10688,11 +10782,20 @@ impl<'a, C, A> EditInsertCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10715,7 +10818,7 @@ impl<'a, C, A> EditInsertCall<'a, C, A> where C: BorrowMut, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -10946,7 +11049,7 @@ impl<'a, C, A> EditListingListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10968,7 +11071,7 @@ impl<'a, C, A> EditListingListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11147,6 +11250,7 @@ impl<'a, C, A> EditTesterPatchCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Testers)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11204,11 +11308,20 @@ impl<'a, C, A> EditTesterPatchCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11231,7 +11344,7 @@ impl<'a, C, A> EditTesterPatchCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11481,7 +11594,7 @@ impl<'a, C, A> EditCommitCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11503,7 +11616,7 @@ impl<'a, C, A> EditCommitCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11732,7 +11845,7 @@ impl<'a, C, A> EditTrackListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11754,7 +11867,7 @@ impl<'a, C, A> EditTrackListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11983,7 +12096,7 @@ impl<'a, C, A> EditValidateCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12005,7 +12118,7 @@ impl<'a, C, A> EditValidateCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12186,6 +12299,7 @@ impl<'a, C, A> EditListingUpdateCall<'a, C, A> where C: BorrowMut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Listing)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12243,11 +12357,20 @@ impl<'a, C, A> EditListingUpdateCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12270,7 +12393,7 @@ impl<'a, C, A> EditListingUpdateCall<'a, C, A> where C: BorrowMut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -12525,7 +12648,7 @@ impl<'a, C, A> EditExpansionfileGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12547,7 +12670,7 @@ impl<'a, C, A> EditExpansionfileGetCall<'a, C, A> where C: BorrowMut EditImageDeleteallCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12821,7 +12944,7 @@ impl<'a, C, A> EditImageDeleteallCall<'a, C, A> where C: BorrowMut EditDetailPatchCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AppDetails)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13076,11 +13200,20 @@ impl<'a, C, A> EditDetailPatchCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13103,7 +13236,7 @@ impl<'a, C, A> EditDetailPatchCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -13296,6 +13429,7 @@ impl<'a, C, A> EditTrackPatchCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Track)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13353,11 +13487,20 @@ impl<'a, C, A> EditTrackPatchCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13380,7 +13523,7 @@ impl<'a, C, A> EditTrackPatchCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -13632,7 +13775,7 @@ impl<'a, C, A> EditListingDeleteCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13654,7 +13797,7 @@ impl<'a, C, A> EditListingDeleteCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -13887,7 +14030,7 @@ impl<'a, C, A> EditApklistingGetCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13909,7 +14052,7 @@ impl<'a, C, A> EditApklistingGetCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -14108,6 +14251,7 @@ impl<'a, C, A> EditTesterUpdateCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Testers)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14165,11 +14309,20 @@ impl<'a, C, A> EditTesterUpdateCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14192,7 +14345,7 @@ impl<'a, C, A> EditTesterUpdateCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -14444,7 +14597,7 @@ impl<'a, C, A> EditApklistingListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14466,7 +14619,7 @@ impl<'a, C, A> EditApklistingListCall<'a, C, A> where C: BorrowMut InappproductBatchCall<'a, C, A> where C: BorrowMut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, InappproductsBatchResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14682,11 +14836,20 @@ impl<'a, C, A> InappproductBatchCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14709,7 +14872,7 @@ impl<'a, C, A> InappproductBatchCall<'a, C, A> where C: BorrowMut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -14943,7 +15106,7 @@ impl<'a, C, A> InappproductListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14965,7 +15128,7 @@ impl<'a, C, A> InappproductListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -15154,6 +15317,7 @@ impl<'a, C, A> InappproductInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, InAppProduct)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15212,11 +15376,20 @@ impl<'a, C, A> InappproductInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15239,7 +15412,7 @@ impl<'a, C, A> InappproductInsertCall<'a, C, A> where C: BorrowMut InappproductDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15498,7 +15671,7 @@ impl<'a, C, A> InappproductDeleteCall<'a, C, A> where C: BorrowMut InappproductGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15739,7 +15912,7 @@ impl<'a, C, A> InappproductGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -15920,6 +16093,7 @@ impl<'a, C, A> InappproductUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, InAppProduct)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15979,11 +16153,20 @@ impl<'a, C, A> InappproductUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -16006,7 +16189,7 @@ impl<'a, C, A> InappproductUpdateCall<'a, C, A> where C: BorrowMut InappproductPatchCall<'a, C, A> where C: BorrowMut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, InAppProduct)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -16266,11 +16450,20 @@ impl<'a, C, A> InappproductPatchCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -16293,7 +16486,7 @@ impl<'a, C, A> InappproductPatchCall<'a, C, A> where C: BorrowMut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) diff --git a/gen/appsactivity1-cli/Cargo.toml b/gen/appsactivity1-cli/Cargo.toml index e88c7a6414..5539cf68ae 100644 --- a/gen/appsactivity1-cli/Cargo.toml +++ b/gen/appsactivity1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-appsactivity1-cli" -version = "0.1.0+20140828" +version = "0.2.0+20140828" authors = ["Sebastian Thiel "] description = "A complete library to interact with appsactivity (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/appsactivity1-cli" @@ -17,15 +17,14 @@ keywords = ["appsactivity", "google", "cli"] name = "appsactivity1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-appsactivity1] path = "../appsactivity1" diff --git a/gen/appsactivity1-cli/README.md b/gen/appsactivity1-cli/README.md index 948ff39447..02c4dd4c7c 100644 --- a/gen/appsactivity1-cli/README.md +++ b/gen/appsactivity1-cli/README.md @@ -10,21 +10,23 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *appsactivity* API can be found at the +[official documentation site](https://developers.google.com/google-apps/activity/). + # Usage -This documentation was generated from the *appsactivity* API at revision *20140828*. The CLI is at version *0.1.0*. +This documentation was generated from the *appsactivity* API at revision *20140828*. The CLI is at version *0.2.0*. ```bash - appsactivity1 [options] activities list [-p ...] [-o ] +appsactivity1 [options] + activities + list [-p ]... [-o ] appsactivity1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_appsactivity1_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/appsactivity1-cli/mkdocs.yml b/gen/appsactivity1-cli/mkdocs.yml index 06017bbf9b..ea015ef772 100644 --- a/gen/appsactivity1-cli/mkdocs.yml +++ b/gen/appsactivity1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: appsactivity v0.1.0+20140828 +site_name: appsactivity v0.2.0+20140828 site_url: http://byron.github.io/google-apis-rs/google-appsactivity1-cli site_description: Write integrating applications with bcore diff --git a/gen/appsactivity1-cli/src/cmn.rs b/gen/appsactivity1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/appsactivity1-cli/src/cmn.rs +++ b/gen/appsactivity1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/appsactivity1-cli/src/main.rs b/gen/appsactivity1-cli/src/main.rs index fef8a91a4e..6a12add3d1 100644 --- a/gen/appsactivity1-cli/src/main.rs +++ b/gen/appsactivity1-cli/src/main.rs @@ -2,67 +2,53 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_appsactivity1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - appsactivity1 [options] activities list [-p ...] [-o ] - appsactivity1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_appsactivity1_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Appsactivity>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _activities_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { +impl<'n, 'a> Engine<'n, 'a> { + fn _activities_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.activities().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "user-id" => { @@ -86,73 +72,86 @@ impl Engine { "drive-ancestor-id" => { call = call.drive_ancestor_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["drive-ancestor-id", "page-size", "page-token", "grouping-strategy", "user-id", "drive-file-id", "source"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_activities { - if self.opt.cmd_list { - call_result = self._activities_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("activities", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._activities_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("activities".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -165,7 +164,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -178,7 +177,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -188,37 +187,142 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Appsactivity::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("activities", "methods: 'list'", vec![ + ("list", + Some(r##"Returns a list of activities visible to the current logged in user. Visible activities are determined by the visiblity settings of the object that was acted on, e.g. Drive files a user can see. An activity is a record of past events. Multiple events may be merged if they are similar. A request is scoped to activities from a given Google service using the source parameter."##), + "Details at http://byron.github.io/google-apis-rs/google_appsactivity1_cli/activities_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("appsactivity1") + .author("Sebastian Thiel ") + .version("0.2.0+20140828") + .about("Provides a historical view of activity.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_appsactivity1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/appsactivity1/Cargo.toml b/gen/appsactivity1/Cargo.toml index cce9ee4a42..2898c0344c 100644 --- a/gen/appsactivity1/Cargo.toml +++ b/gen/appsactivity1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-appsactivity1" -version = "0.1.6+20140828" +version = "0.1.7+20140828" authors = ["Sebastian Thiel "] description = "A complete library to interact with appsactivity (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/appsactivity1" @@ -15,9 +15,10 @@ keywords = ["appsactivity", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/appsactivity1/README.md b/gen/appsactivity1/README.md index 9f5bb4477b..3f2f6d2e87 100644 --- a/gen/appsactivity1/README.md +++ b/gen/appsactivity1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-appsactivity1` library allows access to all features of the *Google appsactivity* service. -This documentation was generated from *appsactivity* crate version *0.1.6+20140828*, where *20140828* is the exact revision of the *appsactivity:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *appsactivity* crate version *0.1.7+20140828*, where *20140828* is the exact revision of the *appsactivity:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *appsactivity* *v1* API can be found at the [official documentation site](https://developers.google.com/google-apps/activity/). @@ -164,7 +164,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_appsactivity1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_appsactivity1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/appsactivity1/src/cmn.rs b/gen/appsactivity1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/appsactivity1/src/cmn.rs +++ b/gen/appsactivity1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/appsactivity1/src/lib.rs b/gen/appsactivity1/src/lib.rs index 8c824a3425..3143c2b575 100644 --- a/gen/appsactivity1/src/lib.rs +++ b/gen/appsactivity1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *appsactivity* crate version *0.1.6+20140828*, where *20140828* is the exact revision of the *appsactivity:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *appsactivity* crate version *0.1.7+20140828*, where *20140828* is the exact revision of the *appsactivity:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *appsactivity* *v1* API can be found at the //! [official documentation site](https://developers.google.com/google-apps/activity/). @@ -165,7 +165,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -174,7 +174,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -190,6 +189,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -325,7 +325,7 @@ impl<'a, C, A> Appsactivity Appsactivity { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -334,7 +334,7 @@ impl<'a, C, A> Appsactivity } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -744,7 +744,7 @@ impl<'a, C, A> ActivityListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -766,7 +766,7 @@ impl<'a, C, A> ActivityListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/appstate1-cli/Cargo.toml b/gen/appstate1-cli/Cargo.toml index 3f470fb69c..d30fcdf448 100644 --- a/gen/appstate1-cli/Cargo.toml +++ b/gen/appstate1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-appstate1-cli" -version = "0.1.0+20150414" +version = "0.2.0+20150414" authors = ["Sebastian Thiel "] description = "A complete library to interact with App State (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/appstate1-cli" @@ -17,15 +17,14 @@ keywords = ["appstate", "google", "cli"] name = "appstate1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-appstate1] path = "../appstate1" diff --git a/gen/appstate1-cli/README.md b/gen/appstate1-cli/README.md index f25d840104..4c8a21f02c 100644 --- a/gen/appstate1-cli/README.md +++ b/gen/appstate1-cli/README.md @@ -10,25 +10,27 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *App State* API can be found at the +[official documentation site](https://developers.google.com/games/services/web/api/states). + # Usage -This documentation was generated from the *App State* API at revision *20150414*. The CLI is at version *0.1.0*. +This documentation was generated from the *App State* API at revision *20150414*. The CLI is at version *0.2.0*. ```bash - appstate1 [options] states clear [-p ...] [-o ] - appstate1 [options] states delete [-p ...] - appstate1 [options] states get [-p ...] [-o ] - appstate1 [options] states list [-p ...] [-o ] - appstate1 [options] states update -r ... [-p ...] [-o ] +appstate1 [options] + states + clear [-p ]... [-o ] + delete [-p ]... + get [-p ]... [-o ] + list [-p ]... [-o ] + update (-r )... [-p ]... [-o ] appstate1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_appstate1_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/appstate1-cli/mkdocs.yml b/gen/appstate1-cli/mkdocs.yml index 088dd4f66c..93f634399a 100644 --- a/gen/appstate1-cli/mkdocs.yml +++ b/gen/appstate1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: App State v0.1.0+20150414 +site_name: App State v0.2.0+20150414 site_url: http://byron.github.io/google-apis-rs/google-appstate1-cli site_description: Write integrating applications with bcore diff --git a/gen/appstate1-cli/src/cmn.rs b/gen/appstate1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/appstate1-cli/src/cmn.rs +++ b/gen/appstate1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/appstate1-cli/src/main.rs b/gen/appstate1-cli/src/main.rs index c1658245cf..e58e7c4adf 100644 --- a/gen/appstate1-cli/src/main.rs +++ b/gen/appstate1-cli/src/main.rs @@ -2,264 +2,257 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_appstate1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - appstate1 [options] states clear [-p ...] [-o ] - appstate1 [options] states delete [-p ...] - appstate1 [options] states get [-p ...] [-o ] - appstate1 [options] states list [-p ...] [-o ] - appstate1 [options] states update -r ... [-p ...] [-o ] - appstate1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_appstate1_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::AppState>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _states_clear(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let state_key: i32 = arg_from_str(&self.opt.arg_state_key, err, "", "integer"); +impl<'n, 'a> Engine<'n, 'a> { + fn _states_clear(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let state_key: i32 = arg_from_str(&opt.value_of("state-key").unwrap_or(""), err, "", "integer"); let mut call = self.hub.states().clear(state_key); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "current-data-version" => { call = call.current_data_version(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["current-data-version"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _states_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let state_key: i32 = arg_from_str(&self.opt.arg_state_key, err, "", "integer"); + fn _states_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let state_key: i32 = arg_from_str(&opt.value_of("state-key").unwrap_or(""), err, "", "integer"); let mut call = self.hub.states().delete(state_key); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _states_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let state_key: i32 = arg_from_str(&self.opt.arg_state_key, err, "", "integer"); + fn _states_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let state_key: i32 = arg_from_str(&opt.value_of("state-key").unwrap_or(""), err, "", "integer"); let mut call = self.hub.states().get(state_key); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _states_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _states_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.states().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "include-data" => { call = call.include_data(arg_from_str(value.unwrap_or("false"), err, "include-data", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["include-data"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _states_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _states_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UpdateRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -281,93 +274,111 @@ impl Engine { request.data = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["data", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let state_key: i32 = arg_from_str(&self.opt.arg_state_key, err, "", "integer"); + let state_key: i32 = arg_from_str(&opt.value_of("state-key").unwrap_or(""), err, "", "integer"); let mut call = self.hub.states().update(request, state_key); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "current-state-version" => { call = call.current_state_version(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["current-state-version"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_states { - if self.opt.cmd_clear { - call_result = self._states_clear(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._states_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._states_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._states_list(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._states_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("states", Some(opt)) => { + match opt.subcommand() { + ("clear", Some(opt)) => { + call_result = self._states_clear(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._states_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._states_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._states_list(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._states_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("states".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -380,7 +391,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -393,7 +404,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -403,37 +414,230 @@ impl Engine { let engine = Engine { opt: opt, hub: api::AppState::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("states", "methods: 'clear', 'delete', 'get', 'list' and 'update'", vec![ + ("clear", + Some(r##"Clears (sets to empty) the data for the passed key if and only if the passed version matches the currently stored version. This method results in a conflict error on version mismatch."##), + "Details at http://byron.github.io/google-apis-rs/google_appstate1_cli/states_clear", + vec![ + (Some(r##"state-key"##), + None, + Some(r##"The key for the data to be retrieved."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes a key and the data associated with it. The key is removed and no longer counts against the key quota. Note that since this method is not safe in the face of concurrent modifications, it should only be used for development and testing purposes. Invoking this method in shipping code can result in data loss and data corruption."##), + "Details at http://byron.github.io/google-apis-rs/google_appstate1_cli/states_delete", + vec![ + (Some(r##"state-key"##), + None, + Some(r##"The key for the data to be retrieved."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves the data corresponding to the passed key. If the key does not exist on the server, an HTTP 404 will be returned."##), + "Details at http://byron.github.io/google-apis-rs/google_appstate1_cli/states_get", + vec![ + (Some(r##"state-key"##), + None, + Some(r##"The key for the data to be retrieved."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists all the states keys, and optionally the state data."##), + "Details at http://byron.github.io/google-apis-rs/google_appstate1_cli/states_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update the data associated with the input key if and only if the passed version matches the currently stored version. This method is safe in the face of concurrent writes. Maximum per-key size is 128KB."##), + "Details at http://byron.github.io/google-apis-rs/google_appstate1_cli/states_update", + vec![ + (Some(r##"state-key"##), + None, + Some(r##"The key for the data to be retrieved."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("appstate1") + .author("Sebastian Thiel ") + .version("0.2.0+20150414") + .about("The Google App State API.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_appstate1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/appstate1/Cargo.toml b/gen/appstate1/Cargo.toml index 6b9c642847..1bc54f47b9 100644 --- a/gen/appstate1/Cargo.toml +++ b/gen/appstate1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-appstate1" -version = "0.1.6+20150414" +version = "0.1.7+20150414" authors = ["Sebastian Thiel "] description = "A complete library to interact with App State (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/appstate1" @@ -15,9 +15,10 @@ keywords = ["appstate", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/appstate1/README.md b/gen/appstate1/README.md index a389902cbc..03fc2dc85b 100644 --- a/gen/appstate1/README.md +++ b/gen/appstate1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-appstate1` library allows access to all features of the *Google App State* service. -This documentation was generated from *App State* crate version *0.1.6+20150414*, where *20150414* is the exact revision of the *appstate:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *App State* crate version *0.1.7+20150414*, where *20150414* is the exact revision of the *appstate:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *App State* *v1* API can be found at the [official documentation site](https://developers.google.com/games/services/web/api/states). @@ -165,7 +165,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_appstate1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_appstate1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/appstate1/src/cmn.rs b/gen/appstate1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/appstate1/src/cmn.rs +++ b/gen/appstate1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/appstate1/src/lib.rs b/gen/appstate1/src/lib.rs index bbdc90c807..27e0514ce3 100644 --- a/gen/appstate1/src/lib.rs +++ b/gen/appstate1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *App State* crate version *0.1.6+20150414*, where *20150414* is the exact revision of the *appstate:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *App State* crate version *0.1.7+20150414*, where *20150414* is the exact revision of the *appstate:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *App State* *v1* API can be found at the //! [official documentation site](https://developers.google.com/games/services/web/api/states). @@ -166,7 +166,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -175,7 +175,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -191,6 +190,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -314,7 +314,7 @@ impl<'a, C, A> AppState AppState { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -323,7 +323,7 @@ impl<'a, C, A> AppState } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -669,7 +669,7 @@ impl<'a, C, A> StateDeleteCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -691,7 +691,7 @@ impl<'a, C, A> StateDeleteCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -898,7 +898,7 @@ impl<'a, C, A> StateGetCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -920,7 +920,7 @@ impl<'a, C, A> StateGetCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1142,7 +1142,7 @@ impl<'a, C, A> StateClearCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1164,7 +1164,7 @@ impl<'a, C, A> StateClearCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1367,7 +1367,7 @@ impl<'a, C, A> StateListCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1389,7 +1389,7 @@ impl<'a, C, A> StateListCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1557,6 +1557,7 @@ impl<'a, C, A> StateUpdateCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, WriteResult)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1615,11 +1616,20 @@ impl<'a, C, A> StateUpdateCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1642,7 +1652,7 @@ impl<'a, C, A> StateUpdateCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) diff --git a/gen/audit1-cli/Cargo.toml b/gen/audit1-cli/Cargo.toml index b183c1ca4b..eebc9064bb 100644 --- a/gen/audit1-cli/Cargo.toml +++ b/gen/audit1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-audit1-cli" -version = "0.1.0+20150419" +version = "0.2.0+20150419" authors = ["Sebastian Thiel "] description = "A complete library to interact with audit (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/audit1-cli" @@ -17,15 +17,14 @@ keywords = ["audit", "google", "cli"] name = "audit1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-audit1] path = "../audit1" diff --git a/gen/audit1-cli/README.md b/gen/audit1-cli/README.md index acee88c732..c48c9bda4b 100644 --- a/gen/audit1-cli/README.md +++ b/gen/audit1-cli/README.md @@ -10,17 +10,19 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *audit* API can be found at the +[official documentation site](https://developers.google.com/google-apps/admin-audit/get_started). + # Usage -This documentation was generated from the *audit* API at revision *20150419*. The CLI is at version *0.1.0*. +This documentation was generated from the *audit* API at revision *20150419*. The CLI is at version *0.2.0*. ```bash - audit1 [options] activities list [-p ...] [-o ] +audit1 [options] + activities + list [-p ]... [-o ] audit1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_audit1_cli/index.html - Configuration: --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/audit1-cli/mkdocs.yml b/gen/audit1-cli/mkdocs.yml index a222f5f229..70ba974e01 100644 --- a/gen/audit1-cli/mkdocs.yml +++ b/gen/audit1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: audit v0.1.0+20150419 +site_name: audit v0.2.0+20150419 site_url: http://byron.github.io/google-apis-rs/google-audit1-cli site_description: Write integrating applications with bcore diff --git a/gen/audit1-cli/src/cmn.rs b/gen/audit1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/audit1-cli/src/cmn.rs +++ b/gen/audit1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/audit1-cli/src/main.rs b/gen/audit1-cli/src/main.rs index eb0492e1dc..56b655815e 100644 --- a/gen/audit1-cli/src/main.rs +++ b/gen/audit1-cli/src/main.rs @@ -2,63 +2,53 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_audit1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - audit1 [options] activities list [-p ...] [-o ] - audit1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_audit1_cli/index.html - -Configuration: - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Audit>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _activities_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.activities().list(&self.opt.arg_customer_id, &self.opt.arg_application_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _activities_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.activities().list(opt.value_of("customer-id").unwrap_or(""), opt.value_of("application-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-time" => { @@ -88,70 +78,83 @@ impl Engine { "actor-application-id" => { call = call.actor_application_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["actor-email", "actor-application-id", "actor-ip-address", "caller", "max-results", "event-name", "start-time", "end-time", "continuation-token"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_activities { - if self.opt.cmd_list { - call_result = self._activities_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("activities", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._activities_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("activities".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -164,7 +167,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -177,7 +180,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -187,37 +190,149 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Audit::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("activities", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves a list of activities for a specific customer and application."##), + "Details at http://byron.github.io/google-apis-rs/google_audit1_cli/activities_list", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Represents the customer who is the owner of target object on which action was performed."##), + Some(true), + Some(false)), + + (Some(r##"application-id"##), + None, + Some(r##"Application ID of the application on which the event was performed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("audit1") + .author("Sebastian Thiel ") + .version("0.2.0+20150419") + .about("Lets you access user activities in your enterprise made through various applications.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_audit1_cli") + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/audit1/Cargo.toml b/gen/audit1/Cargo.toml index 69ee8e9cc2..a7f2b47c38 100644 --- a/gen/audit1/Cargo.toml +++ b/gen/audit1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-audit1" -version = "0.1.6+20150419" +version = "0.1.7+20150419" authors = ["Sebastian Thiel "] description = "A complete library to interact with audit (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/audit1" @@ -15,9 +15,10 @@ keywords = ["audit", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/audit1/README.md b/gen/audit1/README.md index a224e18270..d481178e95 100644 --- a/gen/audit1/README.md +++ b/gen/audit1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-audit1` library allows access to all features of the *Google audit* service. -This documentation was generated from *audit* crate version *0.1.6+20150419*, where *20150419* is the exact revision of the *audit:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *audit* crate version *0.1.7+20150419*, where *20150419* is the exact revision of the *audit:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *audit* *v1* API can be found at the [official documentation site](https://developers.google.com/google-apps/admin-audit/get_started). @@ -166,7 +166,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_audit1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_audit1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/audit1/src/cmn.rs b/gen/audit1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/audit1/src/cmn.rs +++ b/gen/audit1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/audit1/src/lib.rs b/gen/audit1/src/lib.rs index a5fb3dad37..83b6dcf2f5 100644 --- a/gen/audit1/src/lib.rs +++ b/gen/audit1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *audit* crate version *0.1.6+20150419*, where *20150419* is the exact revision of the *audit:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *audit* crate version *0.1.7+20150419*, where *20150419* is the exact revision of the *audit:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *audit* *v1* API can be found at the //! [official documentation site](https://developers.google.com/google-apps/admin-audit/get_started). @@ -167,7 +167,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -176,7 +176,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -192,6 +191,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -295,7 +295,7 @@ impl<'a, C, A> Audit Audit { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -304,7 +304,7 @@ impl<'a, C, A> Audit } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -681,7 +681,7 @@ impl<'a, C, A> ActivityListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -689,7 +689,7 @@ impl<'a, C, A> ActivityListCall<'a, C, A> where C: BorrowMut, A: loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); diff --git a/gen/autoscaler1_beta2-cli/Cargo.toml b/gen/autoscaler1_beta2-cli/Cargo.toml index ddf15d69bb..2880d4374c 100644 --- a/gen/autoscaler1_beta2-cli/Cargo.toml +++ b/gen/autoscaler1_beta2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-autoscaler1_beta2-cli" -version = "0.1.0+20141112" +version = "0.2.0+20141112" authors = ["Sebastian Thiel "] description = "A complete library to interact with autoscaler (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/autoscaler1_beta2-cli" @@ -17,15 +17,14 @@ keywords = ["autoscaler", "google", "cli"] name = "autoscaler1-beta2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-autoscaler1_beta2] path = "../autoscaler1_beta2" diff --git a/gen/autoscaler1_beta2-cli/README.md b/gen/autoscaler1_beta2-cli/README.md index a0bc87fbba..bf7760e128 100644 --- a/gen/autoscaler1_beta2-cli/README.md +++ b/gen/autoscaler1_beta2-cli/README.md @@ -10,30 +10,34 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *autoscaler* API can be found at the +[official documentation site](http://developers.google.com/compute/docs/autoscaler). + # Usage -This documentation was generated from the *autoscaler* API at revision *20141112*. The CLI is at version *0.1.0*. +This documentation was generated from the *autoscaler* API at revision *20141112*. The CLI is at version *0.2.0*. ```bash - autoscaler1-beta2 [options] autoscalers delete [-p ...] [-o ] - autoscaler1-beta2 [options] autoscalers get [-p ...] [-o ] - autoscaler1-beta2 [options] autoscalers insert -r ... [-p ...] [-o ] - autoscaler1-beta2 [options] autoscalers list [-p ...] [-o ] - autoscaler1-beta2 [options] autoscalers patch -r ... [-p ...] [-o ] - autoscaler1-beta2 [options] autoscalers update -r ... [-p ...] [-o ] - autoscaler1-beta2 [options] zone-operations delete [-p ...] - autoscaler1-beta2 [options] zone-operations get [-p ...] [-o ] - autoscaler1-beta2 [options] zone-operations list [-p ...] [-o ] - autoscaler1-beta2 [options] zones list [-p ...] [-o ] +autoscaler1-beta2 [options] + autoscalers + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + zone-operations + delete [-p ]... + get [-p ]... [-o ] + list [-p ]... [-o ] + zones + list [-p ]... [-o ] autoscaler1-beta2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_autoscaler1_beta2_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/autoscaler1_beta2-cli/mkdocs.yml b/gen/autoscaler1_beta2-cli/mkdocs.yml index 052476cb1d..93f604ac48 100644 --- a/gen/autoscaler1_beta2-cli/mkdocs.yml +++ b/gen/autoscaler1_beta2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: autoscaler v0.1.0+20141112 +site_name: autoscaler v0.2.0+20141112 site_url: http://byron.github.io/google-apis-rs/google-autoscaler1_beta2-cli site_description: Write integrating applications with bcore diff --git a/gen/autoscaler1_beta2-cli/src/cmn.rs b/gen/autoscaler1_beta2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/autoscaler1_beta2-cli/src/cmn.rs +++ b/gen/autoscaler1_beta2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/autoscaler1_beta2-cli/src/main.rs b/gen/autoscaler1_beta2-cli/src/main.rs index ac3e758196..6487528673 100644 --- a/gen/autoscaler1_beta2-cli/src/main.rs +++ b/gen/autoscaler1_beta2-cli/src/main.rs @@ -2,170 +2,155 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_autoscaler1_beta2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - autoscaler1-beta2 [options] autoscalers delete [-p ...] [-o ] - autoscaler1-beta2 [options] autoscalers get [-p ...] [-o ] - autoscaler1-beta2 [options] autoscalers insert -r ... [-p ...] [-o ] - autoscaler1-beta2 [options] autoscalers list [-p ...] [-o ] - autoscaler1-beta2 [options] autoscalers patch -r ... [-p ...] [-o ] - autoscaler1-beta2 [options] autoscalers update -r ... [-p ...] [-o ] - autoscaler1-beta2 [options] zone-operations delete [-p ...] - autoscaler1-beta2 [options] zone-operations get [-p ...] [-o ] - autoscaler1-beta2 [options] zone-operations list [-p ...] [-o ] - autoscaler1-beta2 [options] zones list [-p ...] [-o ] - autoscaler1-beta2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_autoscaler1_beta2_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::AutoscalerHub>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _autoscalers_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.autoscalers().delete(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_autoscaler); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _autoscalers_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.autoscalers().delete(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("autoscaler").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _autoscalers_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.autoscalers().get(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_autoscaler); - for parg in self.opt.arg_v.iter() { + fn _autoscalers_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.autoscalers().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("autoscaler").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _autoscalers_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _autoscalers_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Autoscaler::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -247,58 +232,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["autoscaling-policy", "cool-down-period-sec", "cpu-utilization", "creation-timestamp", "description", "id", "kind", "load-balancing-utilization", "max-num-replicas", "min-num-replicas", "name", "self-link", "target", "utilization-target"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.autoscalers().insert(request, &self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.autoscalers().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _autoscalers_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.autoscalers().list(&self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + fn _autoscalers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.autoscalers().list(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -310,52 +300,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _autoscalers_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _autoscalers_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Autoscaler::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -437,60 +431,65 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["autoscaling-policy", "cool-down-period-sec", "cpu-utilization", "creation-timestamp", "description", "id", "kind", "load-balancing-utilization", "max-num-replicas", "min-num-replicas", "name", "self-link", "target", "utilization-target"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.autoscalers().patch(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_autoscaler); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.autoscalers().patch(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("autoscaler").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _autoscalers_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _autoscalers_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Autoscaler::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -572,148 +571,156 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["autoscaling-policy", "cool-down-period-sec", "cpu-utilization", "creation-timestamp", "description", "id", "kind", "load-balancing-utilization", "max-num-replicas", "min-num-replicas", "name", "self-link", "target", "utilization-target"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.autoscalers().update(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_autoscaler); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.autoscalers().update(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("autoscaler").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_operations_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.zone_operations().delete(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_operation); - for parg in self.opt.arg_v.iter() { + fn _zone_operations_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_operations().delete(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("operation").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _zone_operations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.zone_operations().get(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_operation); - for parg in self.opt.arg_v.iter() { + fn _zone_operations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_operations().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("operation").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_operations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.zone_operations().list(&self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + fn _zone_operations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_operations().list(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -725,50 +732,54 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zones_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.zones().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _zones_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zones().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -780,101 +791,129 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_autoscalers { - if self.opt.cmd_delete { - call_result = self._autoscalers_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._autoscalers_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._autoscalers_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._autoscalers_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._autoscalers_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._autoscalers_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("autoscalers", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._autoscalers_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._autoscalers_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._autoscalers_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._autoscalers_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._autoscalers_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._autoscalers_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("autoscalers".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("zone-operations", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._zone_operations_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._zone_operations_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._zone_operations_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("zone-operations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("zones", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._zones_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("zones".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_zone_operations { - if self.opt.cmd_delete { - call_result = self._zone_operations_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._zone_operations_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._zone_operations_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_zones { - if self.opt.cmd_list { - call_result = self._zones_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -887,7 +926,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -900,7 +939,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -910,37 +949,454 @@ impl Engine { let engine = Engine { opt: opt, hub: api::AutoscalerHub::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("autoscalers", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes the specified Autoscaler resource."##), + "Details at http://byron.github.io/google-apis-rs/google_autoscaler1_beta2_cli/autoscalers_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Zone name of Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"autoscaler"##), + None, + Some(r##"Name of the Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Gets the specified Autoscaler resource."##), + "Details at http://byron.github.io/google-apis-rs/google_autoscaler1_beta2_cli/autoscalers_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Zone name of Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"autoscaler"##), + None, + Some(r##"Name of the Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Adds new Autoscaler resource."##), + "Details at http://byron.github.io/google-apis-rs/google_autoscaler1_beta2_cli/autoscalers_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Zone name of Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists all Autoscaler resources in this zone."##), + "Details at http://byron.github.io/google-apis-rs/google_autoscaler1_beta2_cli/autoscalers_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Zone name of Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update the entire content of the Autoscaler resource. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_autoscaler1_beta2_cli/autoscalers_patch", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Zone name of Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"autoscaler"##), + None, + Some(r##"Name of the Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update the entire content of the Autoscaler resource."##), + "Details at http://byron.github.io/google-apis-rs/google_autoscaler1_beta2_cli/autoscalers_update", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Zone name of Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"autoscaler"##), + None, + Some(r##"Name of the Autoscaler resource."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("zone-operations", "methods: 'delete', 'get' and 'list'", vec![ + ("delete", + Some(r##"Deletes the specified zone-specific operation resource."##), + "Details at http://byron.github.io/google-apis-rs/google_autoscaler1_beta2_cli/zone-operations_delete", + vec![ + (Some(r##"project"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"operation"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves the specified zone-specific operation resource."##), + "Details at http://byron.github.io/google-apis-rs/google_autoscaler1_beta2_cli/zone-operations_get", + vec![ + (Some(r##"project"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"operation"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of operation resources contained within the specified zone."##), + "Details at http://byron.github.io/google-apis-rs/google_autoscaler1_beta2_cli/zone-operations_list", + vec![ + (Some(r##"project"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("zones", "methods: 'list'", vec![ + ("list", + Some(r##""##), + "Details at http://byron.github.io/google-apis-rs/google_autoscaler1_beta2_cli/zones_list", + vec![ + (Some(r##"project"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("autoscaler1-beta2") + .author("Sebastian Thiel ") + .version("0.2.0+20141112") + .about("The Google Compute Engine Autoscaler API provides autoscaling for groups of Cloud VMs.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_autoscaler1_beta2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/autoscaler1_beta2/Cargo.toml b/gen/autoscaler1_beta2/Cargo.toml index 3cccdda204..f0bcc73981 100644 --- a/gen/autoscaler1_beta2/Cargo.toml +++ b/gen/autoscaler1_beta2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-autoscaler1_beta2" -version = "0.1.6+20141112" +version = "0.1.7+20141112" authors = ["Sebastian Thiel "] description = "A complete library to interact with autoscaler (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/autoscaler1_beta2" @@ -15,9 +15,10 @@ keywords = ["autoscaler", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/autoscaler1_beta2/README.md b/gen/autoscaler1_beta2/README.md index 2cc7abe754..45b0aa2b97 100644 --- a/gen/autoscaler1_beta2/README.md +++ b/gen/autoscaler1_beta2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-autoscaler1_beta2` library allows access to all features of the *Google autoscaler* service. -This documentation was generated from *autoscaler* crate version *0.1.6+20141112*, where *20141112* is the exact revision of the *autoscaler:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *autoscaler* crate version *0.1.7+20141112*, where *20141112* is the exact revision of the *autoscaler:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *autoscaler* *v1_beta2* API can be found at the [official documentation site](http://developers.google.com/compute/docs/autoscaler). @@ -169,7 +169,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_autoscaler1_beta2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_autoscaler1_beta2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/autoscaler1_beta2/src/cmn.rs b/gen/autoscaler1_beta2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/autoscaler1_beta2/src/cmn.rs +++ b/gen/autoscaler1_beta2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/autoscaler1_beta2/src/lib.rs b/gen/autoscaler1_beta2/src/lib.rs index e4cc981c83..cf6e931491 100644 --- a/gen/autoscaler1_beta2/src/lib.rs +++ b/gen/autoscaler1_beta2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *autoscaler* crate version *0.1.6+20141112*, where *20141112* is the exact revision of the *autoscaler:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *autoscaler* crate version *0.1.7+20141112*, where *20141112* is the exact revision of the *autoscaler:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *autoscaler* *v1_beta2* API can be found at the //! [official documentation site](http://developers.google.com/compute/docs/autoscaler). @@ -170,7 +170,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -179,7 +179,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -195,6 +194,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -318,7 +318,7 @@ impl<'a, C, A> AutoscalerHub AutoscalerHub { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -333,7 +333,7 @@ impl<'a, C, A> AutoscalerHub } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1234,7 +1234,7 @@ impl<'a, C, A> ZoneListCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1256,7 +1256,7 @@ impl<'a, C, A> ZoneListCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1507,7 +1507,7 @@ impl<'a, C, A> ZoneOperationListCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1529,7 +1529,7 @@ impl<'a, C, A> ZoneOperationListCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1775,7 +1775,7 @@ impl<'a, C, A> ZoneOperationDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1797,7 +1797,7 @@ impl<'a, C, A> ZoneOperationDeleteCall<'a, C, A> where C: BorrowMut ZoneOperationGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2047,7 +2047,7 @@ impl<'a, C, A> ZoneOperationGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2298,7 +2298,7 @@ impl<'a, C, A> AutoscalerListCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2320,7 +2320,7 @@ impl<'a, C, A> AutoscalerListCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2519,6 +2519,7 @@ impl<'a, C, A> AutoscalerUpdateCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2576,11 +2577,20 @@ impl<'a, C, A> AutoscalerUpdateCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2603,7 +2613,7 @@ impl<'a, C, A> AutoscalerUpdateCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2806,6 +2816,7 @@ impl<'a, C, A> AutoscalerPatchCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2863,11 +2874,20 @@ impl<'a, C, A> AutoscalerPatchCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2890,7 +2910,7 @@ impl<'a, C, A> AutoscalerPatchCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3143,7 +3163,7 @@ impl<'a, C, A> AutoscalerDeleteCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3165,7 +3185,7 @@ impl<'a, C, A> AutoscalerDeleteCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3355,6 +3375,7 @@ impl<'a, C, A> AutoscalerInsertCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3411,11 +3432,20 @@ impl<'a, C, A> AutoscalerInsertCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3438,7 +3468,7 @@ impl<'a, C, A> AutoscalerInsertCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3681,7 +3711,7 @@ impl<'a, C, A> AutoscalerGetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3703,7 +3733,7 @@ impl<'a, C, A> AutoscalerGetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/bigquery2-cli/Cargo.toml b/gen/bigquery2-cli/Cargo.toml index c54405421a..1e2c8232db 100644 --- a/gen/bigquery2-cli/Cargo.toml +++ b/gen/bigquery2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-bigquery2-cli" -version = "0.1.0+20150326" +version = "0.2.0+20150326" authors = ["Sebastian Thiel "] description = "A complete library to interact with bigquery (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/bigquery2-cli" @@ -17,15 +17,14 @@ keywords = ["bigquery", "google", "cli"] name = "bigquery2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-bigquery2] path = "../bigquery2" diff --git a/gen/bigquery2-cli/README.md b/gen/bigquery2-cli/README.md index 7be0ecb22e..a003655ad0 100644 --- a/gen/bigquery2-cli/README.md +++ b/gen/bigquery2-cli/README.md @@ -10,40 +10,46 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *bigquery* API can be found at the +[official documentation site](https://cloud.google.com/bigquery/). + # Usage -This documentation was generated from the *bigquery* API at revision *20150326*. The CLI is at version *0.1.0*. +This documentation was generated from the *bigquery* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - bigquery2 [options] datasets delete [-p ...] - bigquery2 [options] datasets get [-p ...] [-o ] - bigquery2 [options] datasets insert -r ... [-p ...] [-o ] - bigquery2 [options] datasets list [-p ...] [-o ] - bigquery2 [options] datasets patch -r ... [-p ...] [-o ] - bigquery2 [options] datasets update -r ... [-p ...] [-o ] - bigquery2 [options] jobs get [-p ...] [-o ] - bigquery2 [options] jobs get-query-results [-p ...] [-o ] - bigquery2 [options] jobs insert -r ... -u (simple|resumable) [-p ...] [-o ] - bigquery2 [options] jobs list [-p ...] [-o ] - bigquery2 [options] jobs query -r ... [-p ...] [-o ] - bigquery2 [options] projects list [-p ...] [-o ] - bigquery2 [options] tabledata insert-all -r ... [-p ...] [-o ] - bigquery2 [options] tabledata list [-p ...] [-o ] - bigquery2 [options] tables delete [-p ...] - bigquery2 [options] tables get [-p ...] [-o ] - bigquery2 [options] tables insert -r ... [-p ...] [-o ] - bigquery2 [options] tables list [-p ...] [-o ] - bigquery2 [options] tables patch -r ... [-p ...] [-o ] - bigquery2 [options] tables update -r ... [-p ...] [-o ] +bigquery2 [options] + datasets + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + jobs + get [-p ]... [-o ] + get-query-results [-p ]... [-o ] + insert (-r )... (-u (simple|resumable) -f [-m ]) [-p ]... [-o ] + list [-p ]... [-o ] + query (-r )... [-p ]... [-o ] + projects + list [-p ]... [-o ] + tabledata + insert-all (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + tables + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] bigquery2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_bigquery2_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/bigquery2-cli/mkdocs.yml b/gen/bigquery2-cli/mkdocs.yml index 903cbb5d7e..065b39b801 100644 --- a/gen/bigquery2-cli/mkdocs.yml +++ b/gen/bigquery2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: bigquery v0.1.0+20150326 +site_name: bigquery v0.2.0+20150326 site_url: http://byron.github.io/google-apis-rs/google-bigquery2-cli site_description: Write integrating applications with bcore diff --git a/gen/bigquery2-cli/src/cmn.rs b/gen/bigquery2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/bigquery2-cli/src/cmn.rs +++ b/gen/bigquery2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/bigquery2-cli/src/main.rs b/gen/bigquery2-cli/src/main.rs index 9c61640b3b..e15c62c915 100644 --- a/gen/bigquery2-cli/src/main.rs +++ b/gen/bigquery2-cli/src/main.rs @@ -2,181 +2,151 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_bigquery2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - bigquery2 [options] datasets delete [-p ...] - bigquery2 [options] datasets get [-p ...] [-o ] - bigquery2 [options] datasets insert -r ... [-p ...] [-o ] - bigquery2 [options] datasets list [-p ...] [-o ] - bigquery2 [options] datasets patch -r ... [-p ...] [-o ] - bigquery2 [options] datasets update -r ... [-p ...] [-o ] - bigquery2 [options] jobs get [-p ...] [-o ] - bigquery2 [options] jobs get-query-results [-p ...] [-o ] - bigquery2 [options] jobs insert -r ... -u (simple|resumable) [-p ...] [-o ] - bigquery2 [options] jobs list [-p ...] [-o ] - bigquery2 [options] jobs query -r ... [-p ...] [-o ] - bigquery2 [options] projects list [-p ...] [-o ] - bigquery2 [options] tabledata insert-all -r ... [-p ...] [-o ] - bigquery2 [options] tabledata list [-p ...] [-o ] - bigquery2 [options] tables delete [-p ...] - bigquery2 [options] tables get [-p ...] [-o ] - bigquery2 [options] tables insert -r ... [-p ...] [-o ] - bigquery2 [options] tables list [-p ...] [-o ] - bigquery2 [options] tables patch -r ... [-p ...] [-o ] - bigquery2 [options] tables update -r ... [-p ...] [-o ] - bigquery2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_bigquery2_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Bigquery>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _datasets_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.datasets().delete(&self.opt.arg_project_id, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _datasets_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.datasets().delete(opt.value_of("project-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "delete-contents" => { call = call.delete_contents(arg_from_str(value.unwrap_or("false"), err, "delete-contents", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["delete-contents"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _datasets_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.datasets().get(&self.opt.arg_project_id, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + fn _datasets_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.datasets().get(opt.value_of("project-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _datasets_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Dataset::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -240,58 +210,63 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-time", "dataset-id", "dataset-reference", "default-table-expiration-ms", "description", "etag", "friendly-name", "id", "kind", "last-modified-time", "project-id", "self-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.datasets().insert(request, &self.opt.arg_project_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.datasets().insert(request, opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.datasets().list(&self.opt.arg_project_id); - for parg in self.opt.arg_v.iter() { + fn _datasets_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.datasets().list(opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -303,52 +278,56 @@ impl Engine { "all" => { call = call.all(arg_from_str(value.unwrap_or("false"), err, "all", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "all", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _datasets_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Dataset::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -412,60 +391,65 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-time", "dataset-id", "dataset-reference", "default-table-expiration-ms", "description", "etag", "friendly-name", "id", "kind", "last-modified-time", "project-id", "self-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.datasets().patch(request, &self.opt.arg_project_id, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.datasets().patch(request, opt.value_of("project-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _datasets_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Dataset::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -529,104 +513,113 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-time", "dataset-id", "dataset-reference", "default-table-expiration-ms", "description", "etag", "friendly-name", "id", "kind", "last-modified-time", "project-id", "self-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.datasets().update(request, &self.opt.arg_project_id, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.datasets().update(request, opt.value_of("project-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _jobs_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.jobs().get(&self.opt.arg_project_id, &self.opt.arg_job_id); - for parg in self.opt.arg_v.iter() { + fn _jobs_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.jobs().get(opt.value_of("project-id").unwrap_or(""), opt.value_of("job-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _jobs_get_query_results(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.jobs().get_query_results(&self.opt.arg_project_id, &self.opt.arg_job_id); - for parg in self.opt.arg_v.iter() { + fn _jobs_get_query_results(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.jobs().get_query_results(opt.value_of("project-id").unwrap_or(""), opt.value_of("job-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "timeout-ms" => { @@ -641,52 +634,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["timeout-ms", "page-token", "start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _jobs_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _jobs_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Job::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1165,68 +1162,67 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["allow-jagged-rows", "allow-large-results", "allow-quoted-newlines", "cache-hit", "compression", "configuration", "copy", "create-disposition", "creation-time", "dataset-id", "debug-info", "default-dataset", "destination-format", "destination-table", "destination-uri", "destination-uri-file-counts", "destination-uris", "dry-run", "encoding", "end-time", "error-result", "etag", "extract", "field-delimiter", "flatten-results", "id", "ignore-unknown-values", "input-file-bytes", "input-files", "job-id", "job-reference", "kind", "link", "load", "location", "max-bad-records", "message", "output-bytes", "output-rows", "preserve-nulls", "print-header", "priority", "project-id", "projection-fields", "query", "quote", "reason", "schema-inline", "schema-inline-format", "self-link", "skip-leading-rows", "source-format", "source-table", "source-uri", "source-uris", "start-time", "state", "statistics", "status", "table-id", "total-bytes-processed", "use-query-cache", "user-email", "write-disposition"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.jobs().insert(request, &self.opt.arg_project_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.jobs().insert(request, opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() - }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _jobs_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.jobs().list(&self.opt.arg_project_id); - for parg in self.opt.arg_v.iter() { + fn _jobs_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.jobs().list(opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "state-filter" => { @@ -1244,52 +1240,56 @@ impl Engine { "all-users" => { call = call.all_users(arg_from_str(value.unwrap_or("false"), err, "all-users", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "all-users", "max-results", "projection", "state-filter"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _jobs_query(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _jobs_query(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::QueryRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1343,58 +1343,63 @@ impl Engine { request.preserve_nulls = Some(arg_from_str(value.unwrap_or("false"), err, "preserve-nulls", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["dataset-id", "default-dataset", "dry-run", "kind", "max-results", "preserve-nulls", "project-id", "query", "timeout-ms", "use-query-cache"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.jobs().query(request, &self.opt.arg_project_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.jobs().query(request, opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _projects_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.projects().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1403,52 +1408,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tabledata_insert_all(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _tabledata_insert_all(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TableDataInsertAllRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1473,58 +1482,63 @@ impl Engine { request.skip_invalid_rows = Some(arg_from_str(value.unwrap_or("false"), err, "skip-invalid-rows", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ignore-unknown-values", "kind", "skip-invalid-rows"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tabledata().insert_all(request, &self.opt.arg_project_id, &self.opt.arg_dataset_id, &self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tabledata().insert_all(request, opt.value_of("project-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or(""), opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tabledata_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.tabledata().list(&self.opt.arg_project_id, &self.opt.arg_dataset_id, &self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + fn _tabledata_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tabledata().list(opt.value_of("project-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or(""), opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -1536,142 +1550,149 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.tables().delete(&self.opt.arg_project_id, &self.opt.arg_dataset_id, &self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + fn _tables_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tables().delete(opt.value_of("project-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or(""), opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _tables_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.tables().get(&self.opt.arg_project_id, &self.opt.arg_dataset_id, &self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + fn _tables_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tables().get(opt.value_of("project-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or(""), opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _tables_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Table::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1759,58 +1780,63 @@ impl Engine { request.view.as_mut().unwrap().query = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-time", "dataset-id", "description", "etag", "expiration-time", "friendly-name", "id", "kind", "last-modified-time", "num-bytes", "num-rows", "project-id", "query", "self-link", "table-id", "table-reference", "type", "view"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tables().insert(request, &self.opt.arg_project_id, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tables().insert(request, opt.value_of("project-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.tables().list(&self.opt.arg_project_id, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + fn _tables_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tables().list(opt.value_of("project-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1819,52 +1845,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _tables_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Table::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1952,60 +1982,65 @@ impl Engine { request.view.as_mut().unwrap().query = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-time", "dataset-id", "description", "etag", "expiration-time", "friendly-name", "id", "kind", "last-modified-time", "num-bytes", "num-rows", "project-id", "query", "self-link", "table-id", "table-reference", "type", "view"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tables().patch(request, &self.opt.arg_project_id, &self.opt.arg_dataset_id, &self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tables().patch(request, opt.value_of("project-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or(""), opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _tables_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Table::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2093,139 +2128,184 @@ impl Engine { request.view.as_mut().unwrap().query = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-time", "dataset-id", "description", "etag", "expiration-time", "friendly-name", "id", "kind", "last-modified-time", "num-bytes", "num-rows", "project-id", "query", "self-link", "table-id", "table-reference", "type", "view"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tables().update(request, &self.opt.arg_project_id, &self.opt.arg_dataset_id, &self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tables().update(request, opt.value_of("project-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or(""), opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_datasets { - if self.opt.cmd_delete { - call_result = self._datasets_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._datasets_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._datasets_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._datasets_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._datasets_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._datasets_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("datasets", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._datasets_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._datasets_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._datasets_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._datasets_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._datasets_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._datasets_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("datasets".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("jobs", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._jobs_get(opt, dry_run, &mut err); + }, + ("get-query-results", Some(opt)) => { + call_result = self._jobs_get_query_results(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._jobs_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._jobs_list(opt, dry_run, &mut err); + }, + ("query", Some(opt)) => { + call_result = self._jobs_query(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("jobs".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("projects", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._projects_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("projects".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("tabledata", Some(opt)) => { + match opt.subcommand() { + ("insert-all", Some(opt)) => { + call_result = self._tabledata_insert_all(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._tabledata_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("tabledata".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("tables", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._tables_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._tables_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._tables_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._tables_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._tables_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._tables_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("tables".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_jobs { - if self.opt.cmd_get { - call_result = self._jobs_get(dry_run, &mut err); - } else if self.opt.cmd_get_query_results { - call_result = self._jobs_get_query_results(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._jobs_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._jobs_list(dry_run, &mut err); - } else if self.opt.cmd_query { - call_result = self._jobs_query(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_projects { - if self.opt.cmd_list { - call_result = self._projects_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_tabledata { - if self.opt.cmd_insert_all { - call_result = self._tabledata_insert_all(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._tabledata_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_tables { - if self.opt.cmd_delete { - call_result = self._tables_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._tables_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._tables_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._tables_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._tables_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._tables_update(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -2238,7 +2318,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2251,7 +2331,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2261,37 +2341,752 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Bigquery::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let upload_value_names = ["mode", "file"]; + let arg_data = [ + ("datasets", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes the dataset specified by the datasetId value. Before you can delete a dataset, you must delete all its tables, either manually or by specifying deleteContents. Immediately after deletion, you can create another dataset with the same name."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/datasets_delete", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the dataset being deleted"##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset ID of dataset being deleted"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Returns the dataset specified by datasetID."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/datasets_get", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the requested dataset"##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset ID of the requested dataset"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new empty dataset."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/datasets_insert", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the new dataset"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists all datasets in the specified project to which you have been granted the READER dataset role."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/datasets_list", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the datasets to be listed"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates information in an existing dataset. The update method replaces the entire dataset resource, whereas the patch method only replaces fields that are provided in the submitted dataset resource. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/datasets_patch", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the dataset being updated"##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset ID of the dataset being updated"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates information in an existing dataset. The update method replaces the entire dataset resource, whereas the patch method only replaces fields that are provided in the submitted dataset resource."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/datasets_update", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the dataset being updated"##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset ID of the dataset being updated"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("jobs", "methods: 'get', 'get-query-results', 'insert', 'list' and 'query'", vec![ + ("get", + Some(r##"Returns information about a specific job. Job information is available for a six month period after creation. Requires that you're the person who ran the job, or have the Is Owner project role."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/jobs_get", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the requested job"##), + Some(true), + Some(false)), + + (Some(r##"job-id"##), + None, + Some(r##"Job ID of the requested job"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-query-results", + Some(r##"Retrieves the results of a query job."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/jobs_get-query-results", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the query job"##), + Some(true), + Some(false)), + + (Some(r##"job-id"##), + None, + Some(r##"Job ID of the query job"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Starts a new asynchronous job. Requires the Can View project role."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/jobs_insert", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the project that will be billed for the job"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists all jobs that you started in the specified project. The job list returns in reverse chronological order of when the jobs were created, starting with the most recent job created. Requires the Can View project role, or the Is Owner project role if you set the allUsers property."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/jobs_list", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the jobs to list"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("query", + Some(r##"Runs a BigQuery SQL query synchronously and returns query results if the query completes within a specified timeout."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/jobs_query", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the project billed for the query"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("projects", "methods: 'list'", vec![ + ("list", + Some(r##"Lists all projects to which you have been granted any project role."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/projects_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("tabledata", "methods: 'insert-all' and 'list'", vec![ + ("insert-all", + Some(r##"Streams data into BigQuery one record at a time without needing to run a load job. Requires the WRITER dataset role."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/tabledata_insert-all", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the destination table."##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset ID of the destination table."##), + Some(true), + Some(false)), + + (Some(r##"table-id"##), + None, + Some(r##"Table ID of the destination table."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves table data from a specified set of rows. Requires the READER dataset role."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/tabledata_list", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the table to read"##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset ID of the table to read"##), + Some(true), + Some(false)), + + (Some(r##"table-id"##), + None, + Some(r##"Table ID of the table to read"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("tables", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes the table specified by tableId from the dataset. If the table contains data, all the data will be deleted."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/tables_delete", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the table to delete"##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset ID of the table to delete"##), + Some(true), + Some(false)), + + (Some(r##"table-id"##), + None, + Some(r##"Table ID of the table to delete"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets the specified table resource by table ID. This method does not return the data in the table, it only returns the table resource, which describes the structure of this table."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/tables_get", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the requested table"##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset ID of the requested table"##), + Some(true), + Some(false)), + + (Some(r##"table-id"##), + None, + Some(r##"Table ID of the requested table"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new, empty table in the dataset."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/tables_insert", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the new table"##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset ID of the new table"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists all tables in the specified dataset. Requires the READER dataset role."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/tables_list", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the tables to list"##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset ID of the tables to list"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates information in an existing table. The update method replaces the entire table resource, whereas the patch method only replaces fields that are provided in the submitted table resource. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/tables_patch", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the table to update"##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset ID of the table to update"##), + Some(true), + Some(false)), + + (Some(r##"table-id"##), + None, + Some(r##"Table ID of the table to update"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates information in an existing table. The update method replaces the entire table resource, whereas the patch method only replaces fields that are provided in the submitted table resource."##), + "Details at http://byron.github.io/google-apis-rs/google_bigquery2_cli/tables_update", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"Project ID of the table to update"##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset ID of the table to update"##), + Some(true), + Some(false)), + + (Some(r##"table-id"##), + None, + Some(r##"Table ID of the table to update"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("bigquery2") + .author("Sebastian Thiel ") + .version("0.2.0+20150326") + .about("A data platform for customers to create, manage, share and query data.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_bigquery2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + if arg_name_str == "mode" { + arg = arg.number_of_values(2); + arg = arg.value_names(&upload_value_names); + + scmd = scmd.arg(Arg::with_name("mime") + .short("m") + .requires("mode") + .required(false) + .help("The file's mime time, like 'application/octet-stream'") + .takes_value(true)); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/bigquery2/Cargo.toml b/gen/bigquery2/Cargo.toml index 47dfaa67f5..11af6b2175 100644 --- a/gen/bigquery2/Cargo.toml +++ b/gen/bigquery2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-bigquery2" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel "] description = "A complete library to interact with bigquery (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/bigquery2" @@ -15,9 +15,10 @@ keywords = ["bigquery", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/bigquery2/README.md b/gen/bigquery2/README.md index 9a5bc90de9..ed6b9bb826 100644 --- a/gen/bigquery2/README.md +++ b/gen/bigquery2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-bigquery2` library allows access to all features of the *Google bigquery* service. -This documentation was generated from *bigquery* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *bigquery:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *bigquery* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *bigquery:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *bigquery* *v2* API can be found at the [official documentation site](https://cloud.google.com/bigquery/). @@ -180,7 +180,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_bigquery2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_bigquery2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/bigquery2/src/cmn.rs b/gen/bigquery2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/bigquery2/src/cmn.rs +++ b/gen/bigquery2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/bigquery2/src/lib.rs b/gen/bigquery2/src/lib.rs index 9f827bf631..d2b8701b28 100644 --- a/gen/bigquery2/src/lib.rs +++ b/gen/bigquery2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *bigquery* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *bigquery:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *bigquery* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *bigquery:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *bigquery* *v2* API can be found at the //! [official documentation site](https://cloud.google.com/bigquery/). @@ -181,7 +181,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -190,7 +190,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -206,6 +205,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -348,7 +348,7 @@ impl<'a, C, A> Bigquery Bigquery { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -369,7 +369,7 @@ impl<'a, C, A> Bigquery } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -2244,6 +2244,7 @@ impl<'a, C, A> TableUpdateCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Table)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2301,11 +2302,20 @@ impl<'a, C, A> TableUpdateCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2328,7 +2338,7 @@ impl<'a, C, A> TableUpdateCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2530,6 +2540,7 @@ impl<'a, C, A> TableInsertCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Table)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2586,11 +2597,20 @@ impl<'a, C, A> TableInsertCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2613,7 +2633,7 @@ impl<'a, C, A> TableInsertCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2864,7 +2884,7 @@ impl<'a, C, A> TableListCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2886,7 +2906,7 @@ impl<'a, C, A> TableListCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3130,7 +3150,7 @@ impl<'a, C, A> TableDeleteCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3152,7 +3172,7 @@ impl<'a, C, A> TableDeleteCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3383,7 +3403,7 @@ impl<'a, C, A> TableGetCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3405,7 +3425,7 @@ impl<'a, C, A> TableGetCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3596,6 +3616,7 @@ impl<'a, C, A> TablePatchCall<'a, C, A> where C: BorrowMut, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Table)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3653,11 +3674,20 @@ impl<'a, C, A> TablePatchCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3680,7 +3710,7 @@ impl<'a, C, A> TablePatchCall<'a, C, A> where C: BorrowMut, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3882,6 +3912,7 @@ impl<'a, C, A> DatasetPatchCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Dataset)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3938,11 +3969,20 @@ impl<'a, C, A> DatasetPatchCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3965,7 +4005,7 @@ impl<'a, C, A> DatasetPatchCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4206,7 +4246,7 @@ impl<'a, C, A> DatasetGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4228,7 +4268,7 @@ impl<'a, C, A> DatasetGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4470,7 +4510,7 @@ impl<'a, C, A> DatasetListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4492,7 +4532,7 @@ impl<'a, C, A> DatasetListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4683,6 +4723,7 @@ impl<'a, C, A> DatasetUpdateCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Dataset)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4739,11 +4780,20 @@ impl<'a, C, A> DatasetUpdateCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4766,7 +4816,7 @@ impl<'a, C, A> DatasetUpdateCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5011,7 +5061,7 @@ impl<'a, C, A> DatasetDeleteCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5033,7 +5083,7 @@ impl<'a, C, A> DatasetDeleteCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5209,6 +5259,7 @@ impl<'a, C, A> DatasetInsertCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Dataset)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5264,11 +5315,20 @@ impl<'a, C, A> DatasetInsertCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5291,7 +5351,7 @@ impl<'a, C, A> DatasetInsertCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5472,6 +5532,7 @@ impl<'a, C, A> JobQueryCall<'a, C, A> where C: BorrowMut, A: oaut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, QueryResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5527,11 +5588,20 @@ impl<'a, C, A> JobQueryCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5554,7 +5624,7 @@ impl<'a, C, A> JobQueryCall<'a, C, A> where C: BorrowMut, A: oaut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5805,7 +5875,7 @@ impl<'a, C, A> JobGetQueryResultCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5827,7 +5897,7 @@ impl<'a, C, A> JobGetQueryResultCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6111,7 +6181,7 @@ impl<'a, C, A> JobListCall<'a, C, A> where C: BorrowMut, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6133,7 +6203,7 @@ impl<'a, C, A> JobListCall<'a, C, A> where C: BorrowMut, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6388,7 +6458,7 @@ impl<'a, C, A> JobGetCall<'a, C, A> where C: BorrowMut, A: oauth2 if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6410,7 +6480,7 @@ impl<'a, C, A> JobGetCall<'a, C, A> where C: BorrowMut, A: oauth2 access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6591,6 +6661,7 @@ impl<'a, C, A> JobInsertCall<'a, C, A> where C: BorrowMut, A: oau /// Perform the operation you have build so far. fn doit(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, Job)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6654,11 +6725,20 @@ impl<'a, C, A> JobInsertCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6711,7 +6791,7 @@ impl<'a, C, A> JobInsertCall<'a, C, A> where C: BorrowMut, A: oau _ => (&mut request_value_reader as &mut io::Read, ContentType(json_mime_type.clone())), }; let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(content_type) @@ -6759,7 +6839,7 @@ impl<'a, C, A> JobInsertCall<'a, C, A> where C: BorrowMut, A: oau let upload_result = { let url_str = &res.headers.get::().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -6787,6 +6867,7 @@ impl<'a, C, A> JobInsertCall<'a, C, A> where C: BorrowMut, A: oau Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -6966,6 +7047,7 @@ impl<'a, C, A> TabledataInsertAllCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, TableDataInsertAllResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7023,11 +7105,20 @@ impl<'a, C, A> TabledataInsertAllCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7050,7 +7141,7 @@ impl<'a, C, A> TabledataInsertAllCall<'a, C, A> where C: BorrowMut TabledataListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7340,7 +7431,7 @@ impl<'a, C, A> TabledataListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7582,7 +7673,7 @@ impl<'a, C, A> ProjectListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7604,7 +7695,7 @@ impl<'a, C, A> ProjectListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/blogger3-cli/Cargo.toml b/gen/blogger3-cli/Cargo.toml index 53c0ed7c44..76b4e128ec 100644 --- a/gen/blogger3-cli/Cargo.toml +++ b/gen/blogger3-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-blogger3-cli" -version = "0.1.0+20150422" +version = "0.2.0+20150422" authors = ["Sebastian Thiel "] description = "A complete library to interact with blogger (protocol v3)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/blogger3-cli" @@ -17,15 +17,14 @@ keywords = ["blogger", "google", "cli"] name = "blogger3" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-blogger3] path = "../blogger3" diff --git a/gen/blogger3-cli/README.md b/gen/blogger3-cli/README.md index 5d02d26def..03543375a1 100644 --- a/gen/blogger3-cli/README.md +++ b/gen/blogger3-cli/README.md @@ -10,53 +10,62 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *blogger* API can be found at the +[official documentation site](https://developers.google.com/blogger/docs/3.0/getting_started). + # Usage -This documentation was generated from the *blogger* API at revision *20150422*. The CLI is at version *0.1.0*. +This documentation was generated from the *blogger* API at revision *20150422*. The CLI is at version *0.2.0*. ```bash - blogger3 [options] blog-user-infos get [-p ...] [-o ] - blogger3 [options] blogs get [-p ...] [-o ] - blogger3 [options] blogs get-by-url [-p ...] [-o ] - blogger3 [options] blogs list-by-user [-p ...] [-o ] - blogger3 [options] comments approve [-p ...] [-o ] - blogger3 [options] comments delete [-p ...] - blogger3 [options] comments get [-p ...] [-o ] - blogger3 [options] comments list [-p ...] [-o ] - blogger3 [options] comments list-by-blog [-p ...] [-o ] - blogger3 [options] comments mark-as-spam [-p ...] [-o ] - blogger3 [options] comments remove-content [-p ...] [-o ] - blogger3 [options] page-views get [-p ...] [-o ] - blogger3 [options] pages delete [-p ...] - blogger3 [options] pages get [-p ...] [-o ] - blogger3 [options] pages insert -r ... [-p ...] [-o ] - blogger3 [options] pages list [-p ...] [-o ] - blogger3 [options] pages patch -r ... [-p ...] [-o ] - blogger3 [options] pages publish [-p ...] [-o ] - blogger3 [options] pages revert [-p ...] [-o ] - blogger3 [options] pages update -r ... [-p ...] [-o ] - blogger3 [options] post-user-infos get [-p ...] [-o ] - blogger3 [options] post-user-infos list [-p ...] [-o ] - blogger3 [options] posts delete [-p ...] - blogger3 [options] posts get [-p ...] [-o ] - blogger3 [options] posts get-by-path [-p ...] [-o ] - blogger3 [options] posts insert -r ... [-p ...] [-o ] - blogger3 [options] posts list [-p ...] [-o ] - blogger3 [options] posts patch -r ... [-p ...] [-o ] - blogger3 [options] posts publish [-p ...] [-o ] - blogger3 [options] posts revert [-p ...] [-o ] - blogger3 [options] posts search [-p ...] [-o ] - blogger3 [options] posts update -r ... [-p ...] [-o ] - blogger3 [options] users get [-p ...] [-o ] +blogger3 [options] + blog-user-infos + get [-p ]... [-o ] + blogs + get [-p ]... [-o ] + get-by-url [-p ]... [-o ] + list-by-user [-p ]... [-o ] + comments + approve [-p ]... [-o ] + delete [-p ]... + get [-p ]... [-o ] + list [-p ]... [-o ] + list-by-blog [-p ]... [-o ] + mark-as-spam [-p ]... [-o ] + remove-content [-p ]... [-o ] + page-views + get [-p ]... [-o ] + pages + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + publish [-p ]... [-o ] + revert [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + post-user-infos + get [-p ]... [-o ] + list [-p ]... [-o ] + posts + delete [-p ]... + get [-p ]... [-o ] + get-by-path [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + publish [-p ]... [-o ] + revert [-p ]... [-o ] + search [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + users + get [-p ]... [-o ] blogger3 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_blogger3_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/blogger3-cli/mkdocs.yml b/gen/blogger3-cli/mkdocs.yml index 756a43af63..42f6c1e635 100644 --- a/gen/blogger3-cli/mkdocs.yml +++ b/gen/blogger3-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: blogger v0.1.0+20150422 +site_name: blogger v0.2.0+20150422 site_url: http://byron.github.io/google-apis-rs/google-blogger3-cli site_description: Write integrating applications with bcore diff --git a/gen/blogger3-cli/src/cmn.rs b/gen/blogger3-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/blogger3-cli/src/cmn.rs +++ b/gen/blogger3-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/blogger3-cli/src/main.rs b/gen/blogger3-cli/src/main.rs index cd4f10a952..4c0ea62f0c 100644 --- a/gen/blogger3-cli/src/main.rs +++ b/gen/blogger3-cli/src/main.rs @@ -2,148 +2,106 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_blogger3 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - blogger3 [options] blog-user-infos get [-p ...] [-o ] - blogger3 [options] blogs get [-p ...] [-o ] - blogger3 [options] blogs get-by-url [-p ...] [-o ] - blogger3 [options] blogs list-by-user [-p ...] [-o ] - blogger3 [options] comments approve [-p ...] [-o ] - blogger3 [options] comments delete [-p ...] - blogger3 [options] comments get [-p ...] [-o ] - blogger3 [options] comments list [-p ...] [-o ] - blogger3 [options] comments list-by-blog [-p ...] [-o ] - blogger3 [options] comments mark-as-spam [-p ...] [-o ] - blogger3 [options] comments remove-content [-p ...] [-o ] - blogger3 [options] page-views get [-p ...] [-o ] - blogger3 [options] pages delete [-p ...] - blogger3 [options] pages get [-p ...] [-o ] - blogger3 [options] pages insert -r ... [-p ...] [-o ] - blogger3 [options] pages list [-p ...] [-o ] - blogger3 [options] pages patch -r ... [-p ...] [-o ] - blogger3 [options] pages publish [-p ...] [-o ] - blogger3 [options] pages revert [-p ...] [-o ] - blogger3 [options] pages update -r ... [-p ...] [-o ] - blogger3 [options] post-user-infos get [-p ...] [-o ] - blogger3 [options] post-user-infos list [-p ...] [-o ] - blogger3 [options] posts delete [-p ...] - blogger3 [options] posts get [-p ...] [-o ] - blogger3 [options] posts get-by-path [-p ...] [-o ] - blogger3 [options] posts insert -r ... [-p ...] [-o ] - blogger3 [options] posts list [-p ...] [-o ] - blogger3 [options] posts patch -r ... [-p ...] [-o ] - blogger3 [options] posts publish [-p ...] [-o ] - blogger3 [options] posts revert [-p ...] [-o ] - blogger3 [options] posts search [-p ...] [-o ] - blogger3 [options] posts update -r ... [-p ...] [-o ] - blogger3 [options] users get [-p ...] [-o ] - blogger3 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_blogger3_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Blogger>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _blog_user_infos_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.blog_user_infos().get(&self.opt.arg_user_id, &self.opt.arg_blog_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _blog_user_infos_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.blog_user_infos().get(opt.value_of("user-id").unwrap_or(""), opt.value_of("blog-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "max-posts" => { call = call.max_posts(arg_from_str(value.unwrap_or("-0"), err, "max-posts", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["max-posts"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _blogs_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.blogs().get(&self.opt.arg_blog_id); - for parg in self.opt.arg_v.iter() { + fn _blogs_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.blogs().get(opt.value_of("blog-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "view" => { @@ -152,99 +110,107 @@ impl Engine { "max-posts" => { call = call.max_posts(arg_from_str(value.unwrap_or("-0"), err, "max-posts", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["max-posts", "view"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _blogs_get_by_url(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.blogs().get_by_url(&self.opt.arg_url); - for parg in self.opt.arg_v.iter() { + fn _blogs_get_by_url(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.blogs().get_by_url(opt.value_of("url").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "view" => { call = call.view(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["view"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _blogs_list_by_user(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.blogs().list_by_user(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _blogs_list_by_user(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.blogs().list_by_user(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "view" => { @@ -259,189 +225,200 @@ impl Engine { "fetch-user-info" => { call = call.fetch_user_info(arg_from_str(value.unwrap_or("false"), err, "fetch-user-info", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["status", "fetch-user-info", "role", "view"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _comments_approve(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.comments().approve(&self.opt.arg_blog_id, &self.opt.arg_post_id, &self.opt.arg_comment_id); - for parg in self.opt.arg_v.iter() { + fn _comments_approve(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.comments().approve(opt.value_of("blog-id").unwrap_or(""), opt.value_of("post-id").unwrap_or(""), opt.value_of("comment-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _comments_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.comments().delete(&self.opt.arg_blog_id, &self.opt.arg_post_id, &self.opt.arg_comment_id); - for parg in self.opt.arg_v.iter() { + fn _comments_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.comments().delete(opt.value_of("blog-id").unwrap_or(""), opt.value_of("post-id").unwrap_or(""), opt.value_of("comment-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _comments_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.comments().get(&self.opt.arg_blog_id, &self.opt.arg_post_id, &self.opt.arg_comment_id); - for parg in self.opt.arg_v.iter() { + fn _comments_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.comments().get(opt.value_of("blog-id").unwrap_or(""), opt.value_of("post-id").unwrap_or(""), opt.value_of("comment-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "view" => { call = call.view(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["view"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _comments_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.comments().list(&self.opt.arg_blog_id, &self.opt.arg_post_id); - for parg in self.opt.arg_v.iter() { + fn _comments_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.comments().list(opt.value_of("blog-id").unwrap_or(""), opt.value_of("post-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "view" => { @@ -465,50 +442,54 @@ impl Engine { "end-date" => { call = call.end_date(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["status", "start-date", "end-date", "max-results", "page-token", "fetch-bodies", "view"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _comments_list_by_blog(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.comments().list_by_blog(&self.opt.arg_blog_id); - for parg in self.opt.arg_v.iter() { + fn _comments_list_by_blog(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.comments().list_by_blog(opt.value_of("blog-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "status" => { @@ -529,286 +510,305 @@ impl Engine { "end-date" => { call = call.end_date(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["status", "start-date", "end-date", "max-results", "page-token", "fetch-bodies"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _comments_mark_as_spam(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.comments().mark_as_spam(&self.opt.arg_blog_id, &self.opt.arg_post_id, &self.opt.arg_comment_id); - for parg in self.opt.arg_v.iter() { + fn _comments_mark_as_spam(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.comments().mark_as_spam(opt.value_of("blog-id").unwrap_or(""), opt.value_of("post-id").unwrap_or(""), opt.value_of("comment-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _comments_remove_content(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.comments().remove_content(&self.opt.arg_blog_id, &self.opt.arg_post_id, &self.opt.arg_comment_id); - for parg in self.opt.arg_v.iter() { + fn _comments_remove_content(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.comments().remove_content(opt.value_of("blog-id").unwrap_or(""), opt.value_of("post-id").unwrap_or(""), opt.value_of("comment-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _page_views_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.page_views().get(&self.opt.arg_blog_id); - for parg in self.opt.arg_v.iter() { + fn _page_views_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.page_views().get(opt.value_of("blog-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "range" => { call = call.add_range(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["range"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _pages_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.pages().delete(&self.opt.arg_blog_id, &self.opt.arg_page_id); - for parg in self.opt.arg_v.iter() { + fn _pages_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.pages().delete(opt.value_of("blog-id").unwrap_or(""), opt.value_of("page-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _pages_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.pages().get(&self.opt.arg_blog_id, &self.opt.arg_page_id); - for parg in self.opt.arg_v.iter() { + fn _pages_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.pages().get(opt.value_of("blog-id").unwrap_or(""), opt.value_of("page-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "view" => { call = call.view(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["view"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _pages_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _pages_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Page::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -900,61 +900,66 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author", "blog", "content", "display-name", "etag", "id", "image", "kind", "published", "self-link", "status", "title", "updated", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.pages().insert(request, &self.opt.arg_blog_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.pages().insert(request, opt.value_of("blog-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "is-draft" => { call = call.is_draft(arg_from_str(value.unwrap_or("false"), err, "is-draft", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["is-draft"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _pages_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.pages().list(&self.opt.arg_blog_id); - for parg in self.opt.arg_v.iter() { + fn _pages_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.pages().list(opt.value_of("blog-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "view" => { @@ -972,52 +977,56 @@ impl Engine { "fetch-bodies" => { call = call.fetch_bodies(arg_from_str(value.unwrap_or("false"), err, "fetch-bodies", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["status", "page-token", "fetch-bodies", "max-results", "view"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _pages_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _pages_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Page::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1109,12 +1118,13 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author", "blog", "content", "display-name", "etag", "id", "image", "kind", "published", "self-link", "status", "title", "updated", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.pages().patch(request, &self.opt.arg_blog_id, &self.opt.arg_page_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.pages().patch(request, opt.value_of("blog-id").unwrap_or(""), opt.value_of("page-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "revert" => { @@ -1123,144 +1133,156 @@ impl Engine { "publish" => { call = call.publish(arg_from_str(value.unwrap_or("false"), err, "publish", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["revert", "publish"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _pages_publish(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.pages().publish(&self.opt.arg_blog_id, &self.opt.arg_page_id); - for parg in self.opt.arg_v.iter() { + fn _pages_publish(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.pages().publish(opt.value_of("blog-id").unwrap_or(""), opt.value_of("page-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _pages_revert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.pages().revert(&self.opt.arg_blog_id, &self.opt.arg_page_id); - for parg in self.opt.arg_v.iter() { + fn _pages_revert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.pages().revert(opt.value_of("blog-id").unwrap_or(""), opt.value_of("page-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _pages_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _pages_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Page::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1352,12 +1374,13 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author", "blog", "content", "display-name", "etag", "id", "image", "kind", "published", "self-link", "status", "title", "updated", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.pages().update(request, &self.opt.arg_blog_id, &self.opt.arg_page_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.pages().update(request, opt.value_of("blog-id").unwrap_or(""), opt.value_of("page-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "revert" => { @@ -1366,99 +1389,107 @@ impl Engine { "publish" => { call = call.publish(arg_from_str(value.unwrap_or("false"), err, "publish", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["revert", "publish"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _post_user_infos_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.post_user_infos().get(&self.opt.arg_user_id, &self.opt.arg_blog_id, &self.opt.arg_post_id); - for parg in self.opt.arg_v.iter() { + fn _post_user_infos_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.post_user_infos().get(opt.value_of("user-id").unwrap_or(""), opt.value_of("blog-id").unwrap_or(""), opt.value_of("post-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "max-comments" => { call = call.max_comments(arg_from_str(value.unwrap_or("-0"), err, "max-comments", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["max-comments"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _post_user_infos_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.post_user_infos().list(&self.opt.arg_user_id, &self.opt.arg_blog_id); - for parg in self.opt.arg_v.iter() { + fn _post_user_infos_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.post_user_infos().list(opt.value_of("user-id").unwrap_or(""), opt.value_of("blog-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "view" => { @@ -1488,94 +1519,97 @@ impl Engine { "end-date" => { call = call.end_date(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["status", "start-date", "end-date", "labels", "max-results", "page-token", "order-by", "fetch-bodies", "view"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _posts_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.posts().delete(&self.opt.arg_blog_id, &self.opt.arg_post_id); - for parg in self.opt.arg_v.iter() { + fn _posts_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.posts().delete(opt.value_of("blog-id").unwrap_or(""), opt.value_of("post-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _posts_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.posts().get(&self.opt.arg_blog_id, &self.opt.arg_post_id); - for parg in self.opt.arg_v.iter() { + fn _posts_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.posts().get(opt.value_of("blog-id").unwrap_or(""), opt.value_of("post-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "view" => { @@ -1590,50 +1624,54 @@ impl Engine { "fetch-body" => { call = call.fetch_body(arg_from_str(value.unwrap_or("false"), err, "fetch-body", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["fetch-body", "max-comments", "fetch-images", "view"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _posts_get_by_path(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.posts().get_by_path(&self.opt.arg_blog_id, &self.opt.arg_path); - for parg in self.opt.arg_v.iter() { + fn _posts_get_by_path(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.posts().get_by_path(opt.value_of("blog-id").unwrap_or(""), opt.value_of("path").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "view" => { @@ -1642,52 +1680,56 @@ impl Engine { "max-comments" => { call = call.max_comments(arg_from_str(value.unwrap_or("-0"), err, "max-comments", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["max-comments", "view"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _posts_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _posts_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Post::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1833,12 +1875,13 @@ impl Engine { request.published = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author", "blog", "content", "custom-meta-data", "display-name", "etag", "id", "image", "kind", "labels", "lat", "lng", "location", "name", "published", "reader-comments", "replies", "self-link", "span", "status", "title", "title-link", "total-items", "updated", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.posts().insert(request, &self.opt.arg_blog_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.posts().insert(request, opt.value_of("blog-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "is-draft" => { @@ -1850,50 +1893,54 @@ impl Engine { "fetch-body" => { call = call.fetch_body(arg_from_str(value.unwrap_or("false"), err, "fetch-body", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["fetch-images", "is-draft", "fetch-body"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _posts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.posts().list(&self.opt.arg_blog_id); - for parg in self.opt.arg_v.iter() { + fn _posts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.posts().list(opt.value_of("blog-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "view" => { @@ -1926,52 +1973,56 @@ impl Engine { "end-date" => { call = call.end_date(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["status", "start-date", "end-date", "labels", "max-results", "page-token", "order-by", "fetch-bodies", "fetch-images", "view"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _posts_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _posts_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Post::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2117,12 +2168,13 @@ impl Engine { request.published = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author", "blog", "content", "custom-meta-data", "display-name", "etag", "id", "image", "kind", "labels", "lat", "lng", "location", "name", "published", "reader-comments", "replies", "self-link", "span", "status", "title", "title-link", "total-items", "updated", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.posts().patch(request, &self.opt.arg_blog_id, &self.opt.arg_post_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.posts().patch(request, opt.value_of("blog-id").unwrap_or(""), opt.value_of("post-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "revert" => { @@ -2140,145 +2192,157 @@ impl Engine { "fetch-body" => { call = call.fetch_body(arg_from_str(value.unwrap_or("false"), err, "fetch-body", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["max-comments", "revert", "fetch-images", "publish", "fetch-body"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _posts_publish(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.posts().publish(&self.opt.arg_blog_id, &self.opt.arg_post_id); - for parg in self.opt.arg_v.iter() { + fn _posts_publish(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.posts().publish(opt.value_of("blog-id").unwrap_or(""), opt.value_of("post-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "publish-date" => { call = call.publish_date(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["publish-date"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _posts_revert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.posts().revert(&self.opt.arg_blog_id, &self.opt.arg_post_id); - for parg in self.opt.arg_v.iter() { + fn _posts_revert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.posts().revert(opt.value_of("blog-id").unwrap_or(""), opt.value_of("post-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _posts_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.posts().search(&self.opt.arg_blog_id, &self.opt.arg_q); - for parg in self.opt.arg_v.iter() { + fn _posts_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.posts().search(opt.value_of("blog-id").unwrap_or(""), opt.value_of("q").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "order-by" => { @@ -2287,52 +2351,56 @@ impl Engine { "fetch-bodies" => { call = call.fetch_bodies(arg_from_str(value.unwrap_or("false"), err, "fetch-bodies", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["order-by", "fetch-bodies"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _posts_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _posts_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Post::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2478,12 +2546,13 @@ impl Engine { request.published = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author", "blog", "content", "custom-meta-data", "display-name", "etag", "id", "image", "kind", "labels", "lat", "lng", "location", "name", "published", "reader-comments", "replies", "self-link", "span", "status", "title", "title-link", "total-items", "updated", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.posts().update(request, &self.opt.arg_blog_id, &self.opt.arg_post_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.posts().update(request, opt.value_of("blog-id").unwrap_or(""), opt.value_of("post-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "revert" => { @@ -2501,218 +2570,288 @@ impl Engine { "fetch-body" => { call = call.fetch_body(arg_from_str(value.unwrap_or("false"), err, "fetch-body", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["max-comments", "revert", "fetch-images", "publish", "fetch-body"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.users().get(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _users_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().get(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_blog_user_infos { - if self.opt.cmd_get { - call_result = self._blog_user_infos_get(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("blog-user-infos", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._blog_user_infos_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("blog-user-infos".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("blogs", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._blogs_get(opt, dry_run, &mut err); + }, + ("get-by-url", Some(opt)) => { + call_result = self._blogs_get_by_url(opt, dry_run, &mut err); + }, + ("list-by-user", Some(opt)) => { + call_result = self._blogs_list_by_user(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("blogs".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("comments", Some(opt)) => { + match opt.subcommand() { + ("approve", Some(opt)) => { + call_result = self._comments_approve(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._comments_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._comments_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._comments_list(opt, dry_run, &mut err); + }, + ("list-by-blog", Some(opt)) => { + call_result = self._comments_list_by_blog(opt, dry_run, &mut err); + }, + ("mark-as-spam", Some(opt)) => { + call_result = self._comments_mark_as_spam(opt, dry_run, &mut err); + }, + ("remove-content", Some(opt)) => { + call_result = self._comments_remove_content(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("comments".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("page-views", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._page_views_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("page-views".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("pages", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._pages_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._pages_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._pages_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._pages_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._pages_patch(opt, dry_run, &mut err); + }, + ("publish", Some(opt)) => { + call_result = self._pages_publish(opt, dry_run, &mut err); + }, + ("revert", Some(opt)) => { + call_result = self._pages_revert(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._pages_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("pages".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("post-user-infos", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._post_user_infos_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._post_user_infos_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("post-user-infos".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("posts", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._posts_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._posts_get(opt, dry_run, &mut err); + }, + ("get-by-path", Some(opt)) => { + call_result = self._posts_get_by_path(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._posts_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._posts_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._posts_patch(opt, dry_run, &mut err); + }, + ("publish", Some(opt)) => { + call_result = self._posts_publish(opt, dry_run, &mut err); + }, + ("revert", Some(opt)) => { + call_result = self._posts_revert(opt, dry_run, &mut err); + }, + ("search", Some(opt)) => { + call_result = self._posts_search(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._posts_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("posts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("users", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._users_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("users".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_blogs { - if self.opt.cmd_get { - call_result = self._blogs_get(dry_run, &mut err); - } else if self.opt.cmd_get_by_url { - call_result = self._blogs_get_by_url(dry_run, &mut err); - } else if self.opt.cmd_list_by_user { - call_result = self._blogs_list_by_user(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_comments { - if self.opt.cmd_approve { - call_result = self._comments_approve(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._comments_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._comments_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._comments_list(dry_run, &mut err); - } else if self.opt.cmd_list_by_blog { - call_result = self._comments_list_by_blog(dry_run, &mut err); - } else if self.opt.cmd_mark_as_spam { - call_result = self._comments_mark_as_spam(dry_run, &mut err); - } else if self.opt.cmd_remove_content { - call_result = self._comments_remove_content(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_page_views { - if self.opt.cmd_get { - call_result = self._page_views_get(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_pages { - if self.opt.cmd_delete { - call_result = self._pages_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._pages_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._pages_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._pages_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._pages_patch(dry_run, &mut err); - } else if self.opt.cmd_publish { - call_result = self._pages_publish(dry_run, &mut err); - } else if self.opt.cmd_revert { - call_result = self._pages_revert(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._pages_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_post_user_infos { - if self.opt.cmd_get { - call_result = self._post_user_infos_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._post_user_infos_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_posts { - if self.opt.cmd_delete { - call_result = self._posts_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._posts_get(dry_run, &mut err); - } else if self.opt.cmd_get_by_path { - call_result = self._posts_get_by_path(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._posts_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._posts_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._posts_patch(dry_run, &mut err); - } else if self.opt.cmd_publish { - call_result = self._posts_publish(dry_run, &mut err); - } else if self.opt.cmd_revert { - call_result = self._posts_revert(dry_run, &mut err); - } else if self.opt.cmd_search { - call_result = self._posts_search(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._posts_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_users { - if self.opt.cmd_get { - call_result = self._users_get(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -2725,7 +2864,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2738,7 +2877,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2748,37 +2887,1065 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Blogger::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("blog-user-infos", "methods: 'get'", vec![ + ("get", + Some(r##"Gets one blog and user info pair by blogId and userId."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/blog-user-infos_get", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"ID of the user whose blogs are to be fetched. Either the word 'self' (sans quote marks) or the user's profile identifier."##), + Some(true), + Some(false)), + + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the blog to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("blogs", "methods: 'get', 'get-by-url' and 'list-by-user'", vec![ + ("get", + Some(r##"Gets one blog by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/blogs_get", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the blog to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-by-url", + Some(r##"Retrieve a Blog by URL."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/blogs_get-by-url", + vec![ + (Some(r##"url"##), + None, + Some(r##"The URL of the blog to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-by-user", + Some(r##"Retrieves a list of blogs, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/blogs_list-by-user", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"ID of the user whose blogs are to be fetched. Either the word 'self' (sans quote marks) or the user's profile identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("comments", "methods: 'approve', 'delete', 'get', 'list', 'list-by-blog', 'mark-as-spam' and 'remove-content'", vec![ + ("approve", + Some(r##"Marks a comment as not spam."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/comments_approve", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the Blog."##), + Some(true), + Some(false)), + + (Some(r##"post-id"##), + None, + Some(r##"The ID of the Post."##), + Some(true), + Some(false)), + + (Some(r##"comment-id"##), + None, + Some(r##"The ID of the comment to mark as not spam."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Delete a comment by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/comments_delete", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the Blog."##), + Some(true), + Some(false)), + + (Some(r##"post-id"##), + None, + Some(r##"The ID of the Post."##), + Some(true), + Some(false)), + + (Some(r##"comment-id"##), + None, + Some(r##"The ID of the comment to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets one comment by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/comments_get", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"ID of the blog to containing the comment."##), + Some(true), + Some(false)), + + (Some(r##"post-id"##), + None, + Some(r##"ID of the post to fetch posts from."##), + Some(true), + Some(false)), + + (Some(r##"comment-id"##), + None, + Some(r##"The ID of the comment to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the comments for a post, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/comments_list", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"ID of the blog to fetch comments from."##), + Some(true), + Some(false)), + + (Some(r##"post-id"##), + None, + Some(r##"ID of the post to fetch posts from."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-by-blog", + Some(r##"Retrieves the comments for a blog, across all posts, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/comments_list-by-blog", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"ID of the blog to fetch comments from."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("mark-as-spam", + Some(r##"Marks a comment as spam."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/comments_mark-as-spam", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the Blog."##), + Some(true), + Some(false)), + + (Some(r##"post-id"##), + None, + Some(r##"The ID of the Post."##), + Some(true), + Some(false)), + + (Some(r##"comment-id"##), + None, + Some(r##"The ID of the comment to mark as spam."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("remove-content", + Some(r##"Removes the content of a comment."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/comments_remove-content", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the Blog."##), + Some(true), + Some(false)), + + (Some(r##"post-id"##), + None, + Some(r##"The ID of the Post."##), + Some(true), + Some(false)), + + (Some(r##"comment-id"##), + None, + Some(r##"The ID of the comment to delete content from."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("page-views", "methods: 'get'", vec![ + ("get", + Some(r##"Retrieve pageview stats for a Blog."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/page-views_get", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the blog to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("pages", "methods: 'delete', 'get', 'insert', 'list', 'patch', 'publish', 'revert' and 'update'", vec![ + ("delete", + Some(r##"Delete a page by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/pages_delete", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the Blog."##), + Some(true), + Some(false)), + + (Some(r##"page-id"##), + None, + Some(r##"The ID of the Page."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets one blog page by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/pages_get", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"ID of the blog containing the page."##), + Some(true), + Some(false)), + + (Some(r##"page-id"##), + None, + Some(r##"The ID of the page to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Add a page."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/pages_insert", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"ID of the blog to add the page to."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the pages for a blog, optionally including non-LIVE statuses."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/pages_list", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"ID of the blog to fetch Pages from."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update a page. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/pages_patch", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the Blog."##), + Some(true), + Some(false)), + + (Some(r##"page-id"##), + None, + Some(r##"The ID of the Page."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("publish", + Some(r##"Publishes a draft page."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/pages_publish", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the blog."##), + Some(true), + Some(false)), + + (Some(r##"page-id"##), + None, + Some(r##"The ID of the page."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("revert", + Some(r##"Revert a published or scheduled page to draft state."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/pages_revert", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the blog."##), + Some(true), + Some(false)), + + (Some(r##"page-id"##), + None, + Some(r##"The ID of the page."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update a page."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/pages_update", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the Blog."##), + Some(true), + Some(false)), + + (Some(r##"page-id"##), + None, + Some(r##"The ID of the Page."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("post-user-infos", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one post and user info pair, by post ID and user ID. The post user info contains per-user information about the post, such as access rights, specific to the user."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/post-user-infos_get", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"ID of the user for the per-user information to be fetched. Either the word 'self' (sans quote marks) or the user's profile identifier."##), + Some(true), + Some(false)), + + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the blog."##), + Some(true), + Some(false)), + + (Some(r##"post-id"##), + None, + Some(r##"The ID of the post to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of post and post user info pairs, possibly filtered. The post user info contains per-user information about the post, such as access rights, specific to the user."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/post-user-infos_list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"ID of the user for the per-user information to be fetched. Either the word 'self' (sans quote marks) or the user's profile identifier."##), + Some(true), + Some(false)), + + (Some(r##"blog-id"##), + None, + Some(r##"ID of the blog to fetch posts from."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("posts", "methods: 'delete', 'get', 'get-by-path', 'insert', 'list', 'patch', 'publish', 'revert', 'search' and 'update'", vec![ + ("delete", + Some(r##"Delete a post by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/posts_delete", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the Blog."##), + Some(true), + Some(false)), + + (Some(r##"post-id"##), + None, + Some(r##"The ID of the Post."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Get a post by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/posts_get", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"ID of the blog to fetch the post from."##), + Some(true), + Some(false)), + + (Some(r##"post-id"##), + None, + Some(r##"The ID of the post"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-by-path", + Some(r##"Retrieve a Post by Path."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/posts_get-by-path", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"ID of the blog to fetch the post from."##), + Some(true), + Some(false)), + + (Some(r##"path"##), + None, + Some(r##"Path of the Post to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Add a post."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/posts_insert", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"ID of the blog to add the post to."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of posts, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/posts_list", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"ID of the blog to fetch posts from."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update a post. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/posts_patch", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the Blog."##), + Some(true), + Some(false)), + + (Some(r##"post-id"##), + None, + Some(r##"The ID of the Post."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("publish", + Some(r##"Publishes a draft post, optionally at the specific time of the given publishDate parameter."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/posts_publish", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the Blog."##), + Some(true), + Some(false)), + + (Some(r##"post-id"##), + None, + Some(r##"The ID of the Post."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("revert", + Some(r##"Revert a published or scheduled post to draft state."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/posts_revert", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the Blog."##), + Some(true), + Some(false)), + + (Some(r##"post-id"##), + None, + Some(r##"The ID of the Post."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("search", + Some(r##"Search for a post."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/posts_search", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"ID of the blog to fetch the post from."##), + Some(true), + Some(false)), + + (Some(r##"q"##), + None, + Some(r##"Query terms to search this blog for matching posts."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update a post."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/posts_update", + vec![ + (Some(r##"blog-id"##), + None, + Some(r##"The ID of the Blog."##), + Some(true), + Some(false)), + + (Some(r##"post-id"##), + None, + Some(r##"The ID of the Post."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("users", "methods: 'get'", vec![ + ("get", + Some(r##"Gets one user by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_blogger3_cli/users_get", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("blogger3") + .author("Sebastian Thiel ") + .version("0.2.0+20150422") + .about("API for access to the data within Blogger.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_blogger3_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/blogger3/Cargo.toml b/gen/blogger3/Cargo.toml index bc9a9167d4..114961fe22 100644 --- a/gen/blogger3/Cargo.toml +++ b/gen/blogger3/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-blogger3" -version = "0.1.6+20150422" +version = "0.1.7+20150422" authors = ["Sebastian Thiel "] description = "A complete library to interact with blogger (protocol v3)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/blogger3" @@ -15,9 +15,10 @@ keywords = ["blogger", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/blogger3/README.md b/gen/blogger3/README.md index 3cc61ea5f1..b87fe4cdd3 100644 --- a/gen/blogger3/README.md +++ b/gen/blogger3/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-blogger3` library allows access to all features of the *Google blogger* service. -This documentation was generated from *blogger* crate version *0.1.6+20150422*, where *20150422* is the exact revision of the *blogger:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *blogger* crate version *0.1.7+20150422*, where *20150422* is the exact revision of the *blogger:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *blogger* *v3* API can be found at the [official documentation site](https://developers.google.com/blogger/docs/3.0/getting_started). @@ -190,7 +190,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_blogger3/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_blogger3/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/blogger3/src/cmn.rs b/gen/blogger3/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/blogger3/src/cmn.rs +++ b/gen/blogger3/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/blogger3/src/lib.rs b/gen/blogger3/src/lib.rs index 976655c14f..a2b83fba52 100644 --- a/gen/blogger3/src/lib.rs +++ b/gen/blogger3/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *blogger* crate version *0.1.6+20150422*, where *20150422* is the exact revision of the *blogger:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *blogger* crate version *0.1.7+20150422*, where *20150422* is the exact revision of the *blogger:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *blogger* *v3* API can be found at the //! [official documentation site](https://developers.google.com/blogger/docs/3.0/getting_started). @@ -191,7 +191,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -200,7 +200,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -216,6 +215,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -346,7 +346,7 @@ impl<'a, C, A> Blogger Blogger { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -376,7 +376,7 @@ impl<'a, C, A> Blogger } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -2380,7 +2380,7 @@ impl<'a, C, A> PageViewGetCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2402,7 +2402,7 @@ impl<'a, C, A> PageViewGetCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2626,7 +2626,7 @@ impl<'a, C, A> UserGetCall<'a, C, A> where C: BorrowMut, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2648,7 +2648,7 @@ impl<'a, C, A> UserGetCall<'a, C, A> where C: BorrowMut, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2893,7 +2893,7 @@ impl<'a, C, A> BlogListByUserCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2915,7 +2915,7 @@ impl<'a, C, A> BlogListByUserCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3172,7 +3172,7 @@ impl<'a, C, A> BlogGetCall<'a, C, A> where C: BorrowMut, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3194,7 +3194,7 @@ impl<'a, C, A> BlogGetCall<'a, C, A> where C: BorrowMut, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3406,7 +3406,7 @@ impl<'a, C, A> BlogGetByUrlCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3428,7 +3428,7 @@ impl<'a, C, A> BlogGetByUrlCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3615,6 +3615,7 @@ impl<'a, C, A> PostUpdateCall<'a, C, A> where C: BorrowMut, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Post)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3686,11 +3687,20 @@ impl<'a, C, A> PostUpdateCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3713,7 +3723,7 @@ impl<'a, C, A> PostUpdateCall<'a, C, A> where C: BorrowMut, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3999,7 +4009,7 @@ impl<'a, C, A> PostGetByPathCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4021,7 +4031,7 @@ impl<'a, C, A> PostGetByPathCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4284,7 +4294,7 @@ impl<'a, C, A> PostGetCall<'a, C, A> where C: BorrowMut, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4306,7 +4316,7 @@ impl<'a, C, A> PostGetCall<'a, C, A> where C: BorrowMut, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4519,6 +4529,7 @@ impl<'a, C, A> PostInsertCall<'a, C, A> where C: BorrowMut, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Post)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4583,11 +4594,20 @@ impl<'a, C, A> PostInsertCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4610,7 +4630,7 @@ impl<'a, C, A> PostInsertCall<'a, C, A> where C: BorrowMut, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4867,7 +4887,7 @@ impl<'a, C, A> PostPublishCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4889,7 +4909,7 @@ impl<'a, C, A> PostPublishCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5124,7 +5144,7 @@ impl<'a, C, A> PostDeleteCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5146,7 +5166,7 @@ impl<'a, C, A> PostDeleteCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5365,7 +5385,7 @@ impl<'a, C, A> PostRevertCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5387,7 +5407,7 @@ impl<'a, C, A> PostRevertCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5626,7 +5646,7 @@ impl<'a, C, A> PostSearchCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5648,7 +5668,7 @@ impl<'a, C, A> PostSearchCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5852,6 +5872,7 @@ impl<'a, C, A> PostPatchCall<'a, C, A> where C: BorrowMut, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Post)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5923,11 +5944,20 @@ impl<'a, C, A> PostPatchCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5950,7 +5980,7 @@ impl<'a, C, A> PostPatchCall<'a, C, A> where C: BorrowMut, A: oau request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6278,7 +6308,7 @@ impl<'a, C, A> PostListCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6300,7 +6330,7 @@ impl<'a, C, A> PostListCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6597,7 +6627,7 @@ impl<'a, C, A> CommentGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6619,7 +6649,7 @@ impl<'a, C, A> CommentGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6867,7 +6897,7 @@ impl<'a, C, A> CommentRemoveContentCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6889,7 +6919,7 @@ impl<'a, C, A> CommentRemoveContentCall<'a, C, A> where C: BorrowMut CommentListByBlogCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7182,7 +7212,7 @@ impl<'a, C, A> CommentListByBlogCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7445,7 +7475,7 @@ impl<'a, C, A> CommentMarkAsSpamCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7467,7 +7497,7 @@ impl<'a, C, A> CommentMarkAsSpamCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7745,7 +7775,7 @@ impl<'a, C, A> CommentListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7767,7 +7797,7 @@ impl<'a, C, A> CommentListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8047,7 +8077,7 @@ impl<'a, C, A> CommentApproveCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8069,7 +8099,7 @@ impl<'a, C, A> CommentApproveCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8309,7 +8339,7 @@ impl<'a, C, A> CommentDeleteCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8331,7 +8361,7 @@ impl<'a, C, A> CommentDeleteCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8567,7 +8597,7 @@ impl<'a, C, A> PostUserInfoGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8589,7 +8619,7 @@ impl<'a, C, A> PostUserInfoGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8884,7 +8914,7 @@ impl<'a, C, A> PostUserInfoListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8906,7 +8936,7 @@ impl<'a, C, A> PostUserInfoListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9203,7 +9233,7 @@ impl<'a, C, A> BlogUserInfoGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9225,7 +9255,7 @@ impl<'a, C, A> BlogUserInfoGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9466,7 +9496,7 @@ impl<'a, C, A> PageGetCall<'a, C, A> where C: BorrowMut, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9488,7 +9518,7 @@ impl<'a, C, A> PageGetCall<'a, C, A> where C: BorrowMut, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9750,7 +9780,7 @@ impl<'a, C, A> PageListCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9772,7 +9802,7 @@ impl<'a, C, A> PageListCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10026,7 +10056,7 @@ impl<'a, C, A> PageRevertCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10048,7 +10078,7 @@ impl<'a, C, A> PageRevertCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10229,6 +10259,7 @@ impl<'a, C, A> PageInsertCall<'a, C, A> where C: BorrowMut, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Page)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10287,11 +10318,20 @@ impl<'a, C, A> PageInsertCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10314,7 +10354,7 @@ impl<'a, C, A> PageInsertCall<'a, C, A> where C: BorrowMut, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -10507,6 +10547,7 @@ impl<'a, C, A> PagePatchCall<'a, C, A> where C: BorrowMut, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Page)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10569,11 +10610,20 @@ impl<'a, C, A> PagePatchCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10596,7 +10646,7 @@ impl<'a, C, A> PagePatchCall<'a, C, A> where C: BorrowMut, A: oau request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -10851,7 +10901,7 @@ impl<'a, C, A> PagePublishCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10873,7 +10923,7 @@ impl<'a, C, A> PagePublishCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11057,6 +11107,7 @@ impl<'a, C, A> PageUpdateCall<'a, C, A> where C: BorrowMut, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Page)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11119,11 +11170,20 @@ impl<'a, C, A> PageUpdateCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11146,7 +11206,7 @@ impl<'a, C, A> PageUpdateCall<'a, C, A> where C: BorrowMut, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11400,7 +11460,7 @@ impl<'a, C, A> PageDeleteCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11422,7 +11482,7 @@ impl<'a, C, A> PageDeleteCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/books1-cli/Cargo.toml b/gen/books1-cli/Cargo.toml index 2cb4156082..85d44bcc12 100644 --- a/gen/books1-cli/Cargo.toml +++ b/gen/books1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-books1-cli" -version = "0.1.0+20150401" +version = "0.2.0+20150401" authors = ["Sebastian Thiel "] description = "A complete library to interact with books (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/books1-cli" @@ -17,15 +17,14 @@ keywords = ["books", "google", "cli"] name = "books1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-books1] path = "../books1" diff --git a/gen/books1-cli/README.md b/gen/books1-cli/README.md index 483a184544..c6741d8a96 100644 --- a/gen/books1-cli/README.md +++ b/gen/books1-cli/README.md @@ -10,64 +10,74 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *books* API can be found at the +[official documentation site](https://developers.google.com/books/docs/v1/getting_started). + # Usage -This documentation was generated from the *books* API at revision *20150401*. The CLI is at version *0.1.0*. +This documentation was generated from the *books* API at revision *20150401*. The CLI is at version *0.2.0*. ```bash - books1 [options] bookshelves get [-p ...] [-o ] - books1 [options] bookshelves list [-p ...] [-o ] - books1 [options] bookshelves volumes-list [-p ...] [-o ] - books1 [options] cloudloading add-book [-p ...] [-o ] - books1 [options] cloudloading delete-book [-p ...] - books1 [options] cloudloading update-book -r ... [-p ...] [-o ] - books1 [options] dictionary list-offline-metadata [-p ...] [-o ] - books1 [options] layers annotation-data-get [-p ...] [-o ] - books1 [options] layers annotation-data-list [-p ...] [-o ] - books1 [options] layers get [-p ...] [-o ] - books1 [options] layers list [-p ...] [-o ] - books1 [options] layers volume-annotations-get [-p ...] [-o ] - books1 [options] layers volume-annotations-list [-p ...] [-o ] - books1 [options] myconfig get-user-settings [-p ...] [-o ] - books1 [options] myconfig release-download-access ... [-p ...] [-o ] - books1 [options] myconfig request-access [-p ...] [-o ] - books1 [options] myconfig sync-volume-licenses [-p ...] [-o ] - books1 [options] myconfig update-user-settings -r ... [-p ...] [-o ] - books1 [options] mylibrary annotations-delete [-p ...] - books1 [options] mylibrary annotations-insert -r ... [-p ...] [-o ] - books1 [options] mylibrary annotations-list [-p ...] [-o ] - books1 [options] mylibrary annotations-summary ... [-p ...] [-o ] - books1 [options] mylibrary annotations-update -r ... [-p ...] [-o ] - books1 [options] mylibrary bookshelves-add-volume [-p ...] - books1 [options] mylibrary bookshelves-clear-volumes [-p ...] - books1 [options] mylibrary bookshelves-get [-p ...] [-o ] - books1 [options] mylibrary bookshelves-list [-p ...] [-o ] - books1 [options] mylibrary bookshelves-move-volume [-p ...] - books1 [options] mylibrary bookshelves-remove-volume [-p ...] - books1 [options] mylibrary bookshelves-volumes-list [-p ...] [-o ] - books1 [options] mylibrary readingpositions-get [-p ...] [-o ] - books1 [options] mylibrary readingpositions-set-position [-p ...] - books1 [options] onboarding list-categories [-p ...] [-o ] - books1 [options] onboarding list-category-volumes [-p ...] [-o ] - books1 [options] promooffer accept [-p ...] - books1 [options] promooffer dismiss [-p ...] - books1 [options] promooffer get [-p ...] [-o ] - books1 [options] volumes associated-list [-p ...] [-o ] - books1 [options] volumes get [-p ...] [-o ] - books1 [options] volumes list [-p ...] [-o ] - books1 [options] volumes mybooks-list [-p ...] [-o ] - books1 [options] volumes recommended-list [-p ...] [-o ] - books1 [options] volumes recommended-rate [-p ...] [-o ] - books1 [options] volumes useruploaded-list [-p ...] [-o ] +books1 [options] + bookshelves + get [-p ]... [-o ] + list [-p ]... [-o ] + volumes-list [-p ]... [-o ] + cloudloading + add-book [-p ]... [-o ] + delete-book [-p ]... + update-book (-r )... [-p ]... [-o ] + dictionary + list-offline-metadata [-p ]... [-o ] + layers + annotation-data-get [-p ]... [-o ] + annotation-data-list [-p ]... [-o ] + get [-p ]... [-o ] + list [-p ]... [-o ] + volume-annotations-get [-p ]... [-o ] + volume-annotations-list [-p ]... [-o ] + myconfig + get-user-settings [-p ]... [-o ] + release-download-access ... [-p ]... [-o ] + request-access [-p ]... [-o ] + sync-volume-licenses [-p ]... [-o ] + update-user-settings (-r )... [-p ]... [-o ] + mylibrary + annotations-delete [-p ]... + annotations-insert (-r )... [-p ]... [-o ] + annotations-list [-p ]... [-o ] + annotations-summary ... [-p ]... [-o ] + annotations-update (-r )... [-p ]... [-o ] + bookshelves-add-volume [-p ]... + bookshelves-clear-volumes [-p ]... + bookshelves-get [-p ]... [-o ] + bookshelves-list [-p ]... [-o ] + bookshelves-move-volume [-p ]... + bookshelves-remove-volume [-p ]... + bookshelves-volumes-list [-p ]... [-o ] + readingpositions-get [-p ]... [-o ] + readingpositions-set-position [-p ]... + onboarding + list-categories [-p ]... [-o ] + list-category-volumes [-p ]... [-o ] + promooffer + accept [-p ]... + dismiss [-p ]... + get [-p ]... [-o ] + volumes + associated-list [-p ]... [-o ] + get [-p ]... [-o ] + list [-p ]... [-o ] + mybooks-list [-p ]... [-o ] + recommended-list [-p ]... [-o ] + recommended-rate [-p ]... [-o ] + useruploaded-list [-p ]... [-o ] books1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_books1_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/books1-cli/mkdocs.yml b/gen/books1-cli/mkdocs.yml index 2a48f35c4a..1b62e17069 100644 --- a/gen/books1-cli/mkdocs.yml +++ b/gen/books1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: books v0.1.0+20150401 +site_name: books v0.2.0+20150401 site_url: http://byron.github.io/google-apis-rs/google-books1-cli site_description: Write integrating applications with bcore diff --git a/gen/books1-cli/src/cmn.rs b/gen/books1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/books1-cli/src/cmn.rs +++ b/gen/books1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/books1-cli/src/main.rs b/gen/books1-cli/src/main.rs index b27d6d2d78..caaeb6b0bd 100644 --- a/gen/books1-cli/src/main.rs +++ b/gen/books1-cli/src/main.rs @@ -2,208 +2,159 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_books1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - books1 [options] bookshelves get [-p ...] [-o ] - books1 [options] bookshelves list [-p ...] [-o ] - books1 [options] bookshelves volumes-list [-p ...] [-o ] - books1 [options] cloudloading add-book [-p ...] [-o ] - books1 [options] cloudloading delete-book [-p ...] - books1 [options] cloudloading update-book -r ... [-p ...] [-o ] - books1 [options] dictionary list-offline-metadata [-p ...] [-o ] - books1 [options] layers annotation-data-get [-p ...] [-o ] - books1 [options] layers annotation-data-list [-p ...] [-o ] - books1 [options] layers get [-p ...] [-o ] - books1 [options] layers list [-p ...] [-o ] - books1 [options] layers volume-annotations-get [-p ...] [-o ] - books1 [options] layers volume-annotations-list [-p ...] [-o ] - books1 [options] myconfig get-user-settings [-p ...] [-o ] - books1 [options] myconfig release-download-access ... [-p ...] [-o ] - books1 [options] myconfig request-access [-p ...] [-o ] - books1 [options] myconfig sync-volume-licenses [-p ...] [-o ] - books1 [options] myconfig update-user-settings -r ... [-p ...] [-o ] - books1 [options] mylibrary annotations-delete [-p ...] - books1 [options] mylibrary annotations-insert -r ... [-p ...] [-o ] - books1 [options] mylibrary annotations-list [-p ...] [-o ] - books1 [options] mylibrary annotations-summary ... [-p ...] [-o ] - books1 [options] mylibrary annotations-update -r ... [-p ...] [-o ] - books1 [options] mylibrary bookshelves-add-volume [-p ...] - books1 [options] mylibrary bookshelves-clear-volumes [-p ...] - books1 [options] mylibrary bookshelves-get [-p ...] [-o ] - books1 [options] mylibrary bookshelves-list [-p ...] [-o ] - books1 [options] mylibrary bookshelves-move-volume [-p ...] - books1 [options] mylibrary bookshelves-remove-volume [-p ...] - books1 [options] mylibrary bookshelves-volumes-list [-p ...] [-o ] - books1 [options] mylibrary readingpositions-get [-p ...] [-o ] - books1 [options] mylibrary readingpositions-set-position [-p ...] - books1 [options] onboarding list-categories [-p ...] [-o ] - books1 [options] onboarding list-category-volumes [-p ...] [-o ] - books1 [options] promooffer accept [-p ...] - books1 [options] promooffer dismiss [-p ...] - books1 [options] promooffer get [-p ...] [-o ] - books1 [options] volumes associated-list [-p ...] [-o ] - books1 [options] volumes get [-p ...] [-o ] - books1 [options] volumes list [-p ...] [-o ] - books1 [options] volumes mybooks-list [-p ...] [-o ] - books1 [options] volumes recommended-list [-p ...] [-o ] - books1 [options] volumes recommended-rate [-p ...] [-o ] - books1 [options] volumes useruploaded-list [-p ...] [-o ] - books1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_books1_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Books>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _bookshelves_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.bookshelves().get(&self.opt.arg_user_id, &self.opt.arg_shelf); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _bookshelves_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.bookshelves().get(opt.value_of("user-id").unwrap_or(""), opt.value_of("shelf").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { call = call.source(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _bookshelves_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.bookshelves().list(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _bookshelves_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.bookshelves().list(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { call = call.source(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _bookshelves_volumes_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.bookshelves().volumes_list(&self.opt.arg_user_id, &self.opt.arg_shelf); - for parg in self.opt.arg_v.iter() { + fn _bookshelves_volumes_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.bookshelves().volumes_list(opt.value_of("user-id").unwrap_or(""), opt.value_of("shelf").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -218,50 +169,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source", "start-index", "show-preorders", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _cloudloading_add_book(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _cloudloading_add_book(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.cloudloading().add_book(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "upload-client-token" => { @@ -276,96 +231,99 @@ impl Engine { "drive-document-id" => { call = call.drive_document_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["mime-type", "name", "upload-client-token", "drive-document-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _cloudloading_delete_book(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.cloudloading().delete_book(&self.opt.arg_volume_id); - for parg in self.opt.arg_v.iter() { + fn _cloudloading_delete_book(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.cloudloading().delete_book(opt.value_of("volume-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _cloudloading_update_book(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _cloudloading_update_book(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::BooksCloudloadingResource::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -393,104 +351,113 @@ impl Engine { request.author = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author", "processing-state", "title", "volume-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.cloudloading().update_book(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _dictionary_list_offline_metadata(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.dictionary().list_offline_metadata(&self.opt.arg_cpksver); - for parg in self.opt.arg_v.iter() { + fn _dictionary_list_offline_metadata(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.dictionary().list_offline_metadata(opt.value_of("cpksver").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_annotation_data_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.layers().annotation_data_get(&self.opt.arg_volume_id, &self.opt.arg_layer_id, &self.opt.arg_annotation_data_id, &self.opt.arg_content_version); - for parg in self.opt.arg_v.iter() { + fn _layers_annotation_data_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().annotation_data_get(opt.value_of("volume-id").unwrap_or(""), opt.value_of("layer-id").unwrap_or(""), opt.value_of("annotation-data-id").unwrap_or(""), opt.value_of("content-version").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "w" => { @@ -511,50 +478,54 @@ impl Engine { "allow-web-definitions" => { call = call.allow_web_definitions(arg_from_str(value.unwrap_or("false"), err, "allow-web-definitions", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["scale", "locale", "h", "source", "allow-web-definitions", "w"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_annotation_data_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.layers().annotation_data_list(&self.opt.arg_volume_id, &self.opt.arg_layer_id, &self.opt.arg_content_version); - for parg in self.opt.arg_v.iter() { + fn _layers_annotation_data_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().annotation_data_list(opt.value_of("volume-id").unwrap_or(""), opt.value_of("layer-id").unwrap_or(""), opt.value_of("content-version").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "w" => { @@ -587,50 +558,54 @@ impl Engine { "annotation-data-id" => { call = call.add_annotation_data_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["scale", "source", "locale", "updated-min", "updated-max", "max-results", "annotation-data-id", "page-token", "w", "h"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.layers().get(&self.opt.arg_volume_id, &self.opt.arg_summary_id); - for parg in self.opt.arg_v.iter() { + fn _layers_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().get(opt.value_of("volume-id").unwrap_or(""), opt.value_of("summary-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { @@ -639,50 +614,54 @@ impl Engine { "content-version" => { call = call.content_version(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source", "content-version"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.layers().list(&self.opt.arg_volume_id); - for parg in self.opt.arg_v.iter() { + fn _layers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().list(opt.value_of("volume-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { @@ -697,50 +676,54 @@ impl Engine { "content-version" => { call = call.content_version(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source", "content-version", "max-results", "page-token"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_volume_annotations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.layers().volume_annotations_get(&self.opt.arg_volume_id, &self.opt.arg_layer_id, &self.opt.arg_annotation_id); - for parg in self.opt.arg_v.iter() { + fn _layers_volume_annotations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().volume_annotations_get(opt.value_of("volume-id").unwrap_or(""), opt.value_of("layer-id").unwrap_or(""), opt.value_of("annotation-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { @@ -749,50 +732,54 @@ impl Engine { "locale" => { call = call.locale(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale", "source"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_volume_annotations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.layers().volume_annotations_list(&self.opt.arg_volume_id, &self.opt.arg_layer_id, &self.opt.arg_content_version); - for parg in self.opt.arg_v.iter() { + fn _layers_volume_annotations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().volume_annotations_list(opt.value_of("volume-id").unwrap_or(""), opt.value_of("layer-id").unwrap_or(""), opt.value_of("content-version").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "volume-annotations-version" => { @@ -831,96 +818,104 @@ impl Engine { "end-offset" => { call = call.end_offset(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["show-deleted", "volume-annotations-version", "end-position", "updated-max", "start-position", "updated-min", "end-offset", "max-results", "source", "start-offset", "page-token", "locale"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _myconfig_get_user_settings(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _myconfig_get_user_settings(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.myconfig().get_user_settings(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _myconfig_release_download_access(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.myconfig().release_download_access(&self.opt.arg_volume_ids, &self.opt.arg_cpksver); - for parg in self.opt.arg_v.iter() { + fn _myconfig_release_download_access(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.myconfig().release_download_access(&opt.values_of("volume-ids").unwrap_or(Vec::new()).iter().map(|&v| v.to_string()).collect::>(), opt.value_of("cpksver").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { @@ -929,50 +924,54 @@ impl Engine { "locale" => { call = call.locale(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale", "source"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _myconfig_request_access(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.myconfig().request_access(&self.opt.arg_source, &self.opt.arg_volume_id, &self.opt.arg_nonce, &self.opt.arg_cpksver); - for parg in self.opt.arg_v.iter() { + fn _myconfig_request_access(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.myconfig().request_access(opt.value_of("source").unwrap_or(""), opt.value_of("volume-id").unwrap_or(""), opt.value_of("nonce").unwrap_or(""), opt.value_of("cpksver").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "locale" => { @@ -981,50 +980,54 @@ impl Engine { "license-types" => { call = call.license_types(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale", "license-types"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _myconfig_sync_volume_licenses(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.myconfig().sync_volume_licenses(&self.opt.arg_source, &self.opt.arg_nonce, &self.opt.arg_cpksver); - for parg in self.opt.arg_v.iter() { + fn _myconfig_sync_volume_licenses(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.myconfig().sync_volume_licenses(opt.value_of("source").unwrap_or(""), opt.value_of("nonce").unwrap_or(""), opt.value_of("cpksver").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "volume-ids" => { @@ -1039,52 +1042,56 @@ impl Engine { "features" => { call = call.add_features(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale", "show-preorders", "volume-ids", "features"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _myconfig_update_user_settings(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _myconfig_update_user_settings(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Usersettings::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1117,107 +1124,111 @@ impl Engine { request.notes_export.as_mut().unwrap().folder_name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["folder-name", "is-enabled", "kind", "notes-export"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.myconfig().update_user_settings(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _mylibrary_annotations_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.mylibrary().annotations_delete(&self.opt.arg_annotation_id); - for parg in self.opt.arg_v.iter() { + fn _mylibrary_annotations_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.mylibrary().annotations_delete(opt.value_of("annotation-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { call = call.source(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _mylibrary_annotations_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _mylibrary_annotations_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Annotation::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1509,12 +1520,13 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["after-selected-text", "allowed-character-count", "before-selected-text", "cfi-range", "client-version-ranges", "content-version", "created", "current-version-ranges", "data", "deleted", "end-offset", "end-position", "gb-image-range", "gb-text-range", "highlight-style", "id", "image-cfi-range", "kind", "layer-id", "layer-summary", "limit-type", "page-ids", "remaining-character-count", "selected-text", "self-link", "start-offset", "start-position", "updated", "volume-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.mylibrary().annotations_insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { @@ -1526,50 +1538,54 @@ impl Engine { "country" => { call = call.country(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source", "show-only-summary-in-response", "country"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _mylibrary_annotations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _mylibrary_annotations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.mylibrary().annotations_list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "volume-id" => { @@ -1602,98 +1618,106 @@ impl Engine { "content-version" => { call = call.content_version(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "layer-ids", "show-deleted", "updated-min", "updated-max", "volume-id", "max-results", "source", "content-version", "layer-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _mylibrary_annotations_summary(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.mylibrary().annotations_summary(&self.opt.arg_layer_ids, &self.opt.arg_volume_id); - for parg in self.opt.arg_v.iter() { + fn _mylibrary_annotations_summary(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.mylibrary().annotations_summary(&opt.values_of("layer-ids").unwrap_or(Vec::new()).iter().map(|&v| v.to_string()).collect::>(), opt.value_of("volume-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _mylibrary_annotations_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _mylibrary_annotations_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Annotation::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1985,61 +2009,66 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["after-selected-text", "allowed-character-count", "before-selected-text", "cfi-range", "client-version-ranges", "content-version", "created", "current-version-ranges", "data", "deleted", "end-offset", "end-position", "gb-image-range", "gb-text-range", "highlight-style", "id", "image-cfi-range", "kind", "layer-id", "layer-summary", "limit-type", "page-ids", "remaining-character-count", "selected-text", "self-link", "start-offset", "start-position", "updated", "volume-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.mylibrary().annotations_update(request, &self.opt.arg_annotation_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.mylibrary().annotations_update(request, opt.value_of("annotation-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { call = call.source(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _mylibrary_bookshelves_add_volume(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.mylibrary().bookshelves_add_volume(&self.opt.arg_shelf, &self.opt.arg_volume_id); - for parg in self.opt.arg_v.iter() { + fn _mylibrary_bookshelves_add_volume(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.mylibrary().bookshelves_add_volume(opt.value_of("shelf").unwrap_or(""), opt.value_of("volume-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { @@ -2048,241 +2077,246 @@ impl Engine { "reason" => { call = call.reason(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source", "reason"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _mylibrary_bookshelves_clear_volumes(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.mylibrary().bookshelves_clear_volumes(&self.opt.arg_shelf); - for parg in self.opt.arg_v.iter() { + fn _mylibrary_bookshelves_clear_volumes(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.mylibrary().bookshelves_clear_volumes(opt.value_of("shelf").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { call = call.source(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _mylibrary_bookshelves_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.mylibrary().bookshelves_get(&self.opt.arg_shelf); - for parg in self.opt.arg_v.iter() { + fn _mylibrary_bookshelves_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.mylibrary().bookshelves_get(opt.value_of("shelf").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { call = call.source(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _mylibrary_bookshelves_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _mylibrary_bookshelves_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.mylibrary().bookshelves_list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { call = call.source(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _mylibrary_bookshelves_move_volume(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let volume_position: i32 = arg_from_str(&self.opt.arg_volume_position, err, "", "integer"); - let mut call = self.hub.mylibrary().bookshelves_move_volume(&self.opt.arg_shelf, &self.opt.arg_volume_id, volume_position); - for parg in self.opt.arg_v.iter() { + fn _mylibrary_bookshelves_move_volume(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let volume_position: i32 = arg_from_str(&opt.value_of("volume-position").unwrap_or(""), err, "", "integer"); + let mut call = self.hub.mylibrary().bookshelves_move_volume(opt.value_of("shelf").unwrap_or(""), opt.value_of("volume-id").unwrap_or(""), volume_position); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { call = call.source(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _mylibrary_bookshelves_remove_volume(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.mylibrary().bookshelves_remove_volume(&self.opt.arg_shelf, &self.opt.arg_volume_id); - for parg in self.opt.arg_v.iter() { + fn _mylibrary_bookshelves_remove_volume(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.mylibrary().bookshelves_remove_volume(opt.value_of("shelf").unwrap_or(""), opt.value_of("volume-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { @@ -2291,48 +2325,47 @@ impl Engine { "reason" => { call = call.reason(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source", "reason"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _mylibrary_bookshelves_volumes_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.mylibrary().bookshelves_volumes_list(&self.opt.arg_shelf); - for parg in self.opt.arg_v.iter() { + fn _mylibrary_bookshelves_volumes_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.mylibrary().bookshelves_volumes_list(opt.value_of("shelf").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -2356,50 +2389,54 @@ impl Engine { "country" => { call = call.country(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["projection", "country", "show-preorders", "max-results", "q", "source", "start-index"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _mylibrary_readingpositions_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.mylibrary().readingpositions_get(&self.opt.arg_volume_id); - for parg in self.opt.arg_v.iter() { + fn _mylibrary_readingpositions_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.mylibrary().readingpositions_get(opt.value_of("volume-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { @@ -2408,50 +2445,54 @@ impl Engine { "content-version" => { call = call.content_version(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source", "content-version"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _mylibrary_readingpositions_set_position(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.mylibrary().readingpositions_set_position(&self.opt.arg_volume_id, &self.opt.arg_timestamp, &self.opt.arg_position); - for parg in self.opt.arg_v.iter() { + fn _mylibrary_readingpositions_set_position(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.mylibrary().readingpositions_set_position(opt.value_of("volume-id").unwrap_or(""), opt.value_of("timestamp").unwrap_or(""), opt.value_of("position").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { @@ -2466,97 +2507,100 @@ impl Engine { "action" => { call = call.action(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["action", "source", "content-version", "device-cookie"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _onboarding_list_categories(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _onboarding_list_categories(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.onboarding().list_categories(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "locale" => { call = call.locale(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _onboarding_list_category_volumes(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _onboarding_list_category_volumes(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.onboarding().list_category_volumes(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2571,50 +2615,54 @@ impl Engine { "category-id" => { call = call.add_category_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale", "page-token", "category-id", "page-size"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _promooffer_accept(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _promooffer_accept(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.promooffer().accept(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "volume-id" => { @@ -2641,48 +2689,47 @@ impl Engine { "android-id" => { call = call.android_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["product", "volume-id", "offer-id", "android-id", "device", "model", "serial", "manufacturer"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _promooffer_dismiss(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _promooffer_dismiss(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.promooffer().dismiss(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "serial" => { @@ -2706,48 +2753,47 @@ impl Engine { "android-id" => { call = call.android_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["product", "offer-id", "android-id", "device", "model", "serial", "manufacturer"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _promooffer_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _promooffer_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.promooffer().get(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "serial" => { @@ -2768,50 +2814,54 @@ impl Engine { "android-id" => { call = call.android_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["product", "android-id", "device", "model", "serial", "manufacturer"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _volumes_associated_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.volumes().associated_list(&self.opt.arg_volume_id); - for parg in self.opt.arg_v.iter() { + fn _volumes_associated_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.volumes().associated_list(opt.value_of("volume-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { @@ -2823,50 +2873,54 @@ impl Engine { "association" => { call = call.association(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale", "source", "association"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _volumes_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.volumes().get(&self.opt.arg_volume_id); - for parg in self.opt.arg_v.iter() { + fn _volumes_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.volumes().get(opt.value_of("volume-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "user-library-consistent-read" => { @@ -2884,50 +2938,54 @@ impl Engine { "country" => { call = call.country(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["country", "source", "user-library-consistent-read", "projection", "partner"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _volumes_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.volumes().list(&self.opt.arg_q); - for parg in self.opt.arg_v.iter() { + fn _volumes_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.volumes().list(opt.value_of("q").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -2966,50 +3024,54 @@ impl Engine { "download" => { call = call.download(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["order-by", "projection", "library-restrict", "lang-restrict", "print-type", "show-preorders", "max-results", "filter", "source", "start-index", "download", "partner"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _volumes_mybooks_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _volumes_mybooks_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.volumes().mybooks_list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -3030,50 +3092,54 @@ impl Engine { "acquire-method" => { call = call.add_acquire_method(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale", "acquire-method", "max-results", "source", "start-index", "processing-state"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _volumes_recommended_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _volumes_recommended_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.volumes().recommended_list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { @@ -3082,50 +3148,54 @@ impl Engine { "locale" => { call = call.locale(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale", "source"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _volumes_recommended_rate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.volumes().recommended_rate(&self.opt.arg_rating, &self.opt.arg_volume_id); - for parg in self.opt.arg_v.iter() { + fn _volumes_recommended_rate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.volumes().recommended_rate(opt.value_of("rating").unwrap_or(""), opt.value_of("volume-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { @@ -3134,50 +3204,54 @@ impl Engine { "locale" => { call = call.locale(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale", "source"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _volumes_useruploaded_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _volumes_useruploaded_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.volumes().useruploaded_list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "volume-id" => { @@ -3198,199 +3272,279 @@ impl Engine { "locale" => { call = call.locale(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale", "volume-id", "max-results", "source", "start-index", "processing-state"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_bookshelves { - if self.opt.cmd_get { - call_result = self._bookshelves_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._bookshelves_list(dry_run, &mut err); - } else if self.opt.cmd_volumes_list { - call_result = self._bookshelves_volumes_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("bookshelves", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._bookshelves_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._bookshelves_list(opt, dry_run, &mut err); + }, + ("volumes-list", Some(opt)) => { + call_result = self._bookshelves_volumes_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("bookshelves".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("cloudloading", Some(opt)) => { + match opt.subcommand() { + ("add-book", Some(opt)) => { + call_result = self._cloudloading_add_book(opt, dry_run, &mut err); + }, + ("delete-book", Some(opt)) => { + call_result = self._cloudloading_delete_book(opt, dry_run, &mut err); + }, + ("update-book", Some(opt)) => { + call_result = self._cloudloading_update_book(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("cloudloading".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("dictionary", Some(opt)) => { + match opt.subcommand() { + ("list-offline-metadata", Some(opt)) => { + call_result = self._dictionary_list_offline_metadata(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("dictionary".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("layers", Some(opt)) => { + match opt.subcommand() { + ("annotation-data-get", Some(opt)) => { + call_result = self._layers_annotation_data_get(opt, dry_run, &mut err); + }, + ("annotation-data-list", Some(opt)) => { + call_result = self._layers_annotation_data_list(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._layers_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._layers_list(opt, dry_run, &mut err); + }, + ("volume-annotations-get", Some(opt)) => { + call_result = self._layers_volume_annotations_get(opt, dry_run, &mut err); + }, + ("volume-annotations-list", Some(opt)) => { + call_result = self._layers_volume_annotations_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("layers".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("myconfig", Some(opt)) => { + match opt.subcommand() { + ("get-user-settings", Some(opt)) => { + call_result = self._myconfig_get_user_settings(opt, dry_run, &mut err); + }, + ("release-download-access", Some(opt)) => { + call_result = self._myconfig_release_download_access(opt, dry_run, &mut err); + }, + ("request-access", Some(opt)) => { + call_result = self._myconfig_request_access(opt, dry_run, &mut err); + }, + ("sync-volume-licenses", Some(opt)) => { + call_result = self._myconfig_sync_volume_licenses(opt, dry_run, &mut err); + }, + ("update-user-settings", Some(opt)) => { + call_result = self._myconfig_update_user_settings(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("myconfig".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("mylibrary", Some(opt)) => { + match opt.subcommand() { + ("annotations-delete", Some(opt)) => { + call_result = self._mylibrary_annotations_delete(opt, dry_run, &mut err); + }, + ("annotations-insert", Some(opt)) => { + call_result = self._mylibrary_annotations_insert(opt, dry_run, &mut err); + }, + ("annotations-list", Some(opt)) => { + call_result = self._mylibrary_annotations_list(opt, dry_run, &mut err); + }, + ("annotations-summary", Some(opt)) => { + call_result = self._mylibrary_annotations_summary(opt, dry_run, &mut err); + }, + ("annotations-update", Some(opt)) => { + call_result = self._mylibrary_annotations_update(opt, dry_run, &mut err); + }, + ("bookshelves-add-volume", Some(opt)) => { + call_result = self._mylibrary_bookshelves_add_volume(opt, dry_run, &mut err); + }, + ("bookshelves-clear-volumes", Some(opt)) => { + call_result = self._mylibrary_bookshelves_clear_volumes(opt, dry_run, &mut err); + }, + ("bookshelves-get", Some(opt)) => { + call_result = self._mylibrary_bookshelves_get(opt, dry_run, &mut err); + }, + ("bookshelves-list", Some(opt)) => { + call_result = self._mylibrary_bookshelves_list(opt, dry_run, &mut err); + }, + ("bookshelves-move-volume", Some(opt)) => { + call_result = self._mylibrary_bookshelves_move_volume(opt, dry_run, &mut err); + }, + ("bookshelves-remove-volume", Some(opt)) => { + call_result = self._mylibrary_bookshelves_remove_volume(opt, dry_run, &mut err); + }, + ("bookshelves-volumes-list", Some(opt)) => { + call_result = self._mylibrary_bookshelves_volumes_list(opt, dry_run, &mut err); + }, + ("readingpositions-get", Some(opt)) => { + call_result = self._mylibrary_readingpositions_get(opt, dry_run, &mut err); + }, + ("readingpositions-set-position", Some(opt)) => { + call_result = self._mylibrary_readingpositions_set_position(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("mylibrary".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("onboarding", Some(opt)) => { + match opt.subcommand() { + ("list-categories", Some(opt)) => { + call_result = self._onboarding_list_categories(opt, dry_run, &mut err); + }, + ("list-category-volumes", Some(opt)) => { + call_result = self._onboarding_list_category_volumes(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("onboarding".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("promooffer", Some(opt)) => { + match opt.subcommand() { + ("accept", Some(opt)) => { + call_result = self._promooffer_accept(opt, dry_run, &mut err); + }, + ("dismiss", Some(opt)) => { + call_result = self._promooffer_dismiss(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._promooffer_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("promooffer".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("volumes", Some(opt)) => { + match opt.subcommand() { + ("associated-list", Some(opt)) => { + call_result = self._volumes_associated_list(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._volumes_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._volumes_list(opt, dry_run, &mut err); + }, + ("mybooks-list", Some(opt)) => { + call_result = self._volumes_mybooks_list(opt, dry_run, &mut err); + }, + ("recommended-list", Some(opt)) => { + call_result = self._volumes_recommended_list(opt, dry_run, &mut err); + }, + ("recommended-rate", Some(opt)) => { + call_result = self._volumes_recommended_rate(opt, dry_run, &mut err); + }, + ("useruploaded-list", Some(opt)) => { + call_result = self._volumes_useruploaded_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("volumes".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_cloudloading { - if self.opt.cmd_add_book { - call_result = self._cloudloading_add_book(dry_run, &mut err); - } else if self.opt.cmd_delete_book { - call_result = self._cloudloading_delete_book(dry_run, &mut err); - } else if self.opt.cmd_update_book { - call_result = self._cloudloading_update_book(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_dictionary { - if self.opt.cmd_list_offline_metadata { - call_result = self._dictionary_list_offline_metadata(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_layers { - if self.opt.cmd_annotation_data_get { - call_result = self._layers_annotation_data_get(dry_run, &mut err); - } else if self.opt.cmd_annotation_data_list { - call_result = self._layers_annotation_data_list(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._layers_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._layers_list(dry_run, &mut err); - } else if self.opt.cmd_volume_annotations_get { - call_result = self._layers_volume_annotations_get(dry_run, &mut err); - } else if self.opt.cmd_volume_annotations_list { - call_result = self._layers_volume_annotations_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_myconfig { - if self.opt.cmd_get_user_settings { - call_result = self._myconfig_get_user_settings(dry_run, &mut err); - } else if self.opt.cmd_release_download_access { - call_result = self._myconfig_release_download_access(dry_run, &mut err); - } else if self.opt.cmd_request_access { - call_result = self._myconfig_request_access(dry_run, &mut err); - } else if self.opt.cmd_sync_volume_licenses { - call_result = self._myconfig_sync_volume_licenses(dry_run, &mut err); - } else if self.opt.cmd_update_user_settings { - call_result = self._myconfig_update_user_settings(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_mylibrary { - if self.opt.cmd_annotations_delete { - call_result = self._mylibrary_annotations_delete(dry_run, &mut err); - } else if self.opt.cmd_annotations_insert { - call_result = self._mylibrary_annotations_insert(dry_run, &mut err); - } else if self.opt.cmd_annotations_list { - call_result = self._mylibrary_annotations_list(dry_run, &mut err); - } else if self.opt.cmd_annotations_summary { - call_result = self._mylibrary_annotations_summary(dry_run, &mut err); - } else if self.opt.cmd_annotations_update { - call_result = self._mylibrary_annotations_update(dry_run, &mut err); - } else if self.opt.cmd_bookshelves_add_volume { - call_result = self._mylibrary_bookshelves_add_volume(dry_run, &mut err); - } else if self.opt.cmd_bookshelves_clear_volumes { - call_result = self._mylibrary_bookshelves_clear_volumes(dry_run, &mut err); - } else if self.opt.cmd_bookshelves_get { - call_result = self._mylibrary_bookshelves_get(dry_run, &mut err); - } else if self.opt.cmd_bookshelves_list { - call_result = self._mylibrary_bookshelves_list(dry_run, &mut err); - } else if self.opt.cmd_bookshelves_move_volume { - call_result = self._mylibrary_bookshelves_move_volume(dry_run, &mut err); - } else if self.opt.cmd_bookshelves_remove_volume { - call_result = self._mylibrary_bookshelves_remove_volume(dry_run, &mut err); - } else if self.opt.cmd_bookshelves_volumes_list { - call_result = self._mylibrary_bookshelves_volumes_list(dry_run, &mut err); - } else if self.opt.cmd_readingpositions_get { - call_result = self._mylibrary_readingpositions_get(dry_run, &mut err); - } else if self.opt.cmd_readingpositions_set_position { - call_result = self._mylibrary_readingpositions_set_position(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_onboarding { - if self.opt.cmd_list_categories { - call_result = self._onboarding_list_categories(dry_run, &mut err); - } else if self.opt.cmd_list_category_volumes { - call_result = self._onboarding_list_category_volumes(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_promooffer { - if self.opt.cmd_accept { - call_result = self._promooffer_accept(dry_run, &mut err); - } else if self.opt.cmd_dismiss { - call_result = self._promooffer_dismiss(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._promooffer_get(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_volumes { - if self.opt.cmd_associated_list { - call_result = self._volumes_associated_list(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._volumes_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._volumes_list(dry_run, &mut err); - } else if self.opt.cmd_mybooks_list { - call_result = self._volumes_mybooks_list(dry_run, &mut err); - } else if self.opt.cmd_recommended_list { - call_result = self._volumes_recommended_list(dry_run, &mut err); - } else if self.opt.cmd_recommended_rate { - call_result = self._volumes_recommended_rate(dry_run, &mut err); - } else if self.opt.cmd_useruploaded_list { - call_result = self._volumes_useruploaded_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -3403,7 +3557,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -3416,7 +3570,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -3426,37 +3580,1154 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Books::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("bookshelves", "methods: 'get', 'list' and 'volumes-list'", vec![ + ("get", + Some(r##"Retrieves metadata for a specific bookshelf for the specified user."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/bookshelves_get", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"ID of user for whom to retrieve bookshelves."##), + Some(true), + Some(false)), + + (Some(r##"shelf"##), + None, + Some(r##"ID of bookshelf to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of public bookshelves for the specified user."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/bookshelves_list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"ID of user for whom to retrieve bookshelves."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("volumes-list", + Some(r##"Retrieves volumes in a specific bookshelf for the specified user."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/bookshelves_volumes-list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"ID of user for whom to retrieve bookshelf volumes."##), + Some(true), + Some(false)), + + (Some(r##"shelf"##), + None, + Some(r##"ID of bookshelf to retrieve volumes."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("cloudloading", "methods: 'add-book', 'delete-book' and 'update-book'", vec![ + ("add-book", + Some(r##""##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/cloudloading_add-book", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete-book", + Some(r##"Remove the book and its contents"##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/cloudloading_delete-book", + vec![ + (Some(r##"volume-id"##), + None, + Some(r##"The id of the book to be removed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("update-book", + Some(r##""##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/cloudloading_update-book", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("dictionary", "methods: 'list-offline-metadata'", vec![ + ("list-offline-metadata", + Some(r##"Returns a list of offline dictionary meatadata available"##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/dictionary_list-offline-metadata", + vec![ + (Some(r##"cpksver"##), + None, + Some(r##"The device/version ID from which to request the data."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("layers", "methods: 'annotation-data-get', 'annotation-data-list', 'get', 'list', 'volume-annotations-get' and 'volume-annotations-list'", vec![ + ("annotation-data-get", + Some(r##"Gets the annotation data."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/layers_annotation-data-get", + vec![ + (Some(r##"volume-id"##), + None, + Some(r##"The volume to retrieve annotations for."##), + Some(true), + Some(false)), + + (Some(r##"layer-id"##), + None, + Some(r##"The ID for the layer to get the annotations."##), + Some(true), + Some(false)), + + (Some(r##"annotation-data-id"##), + None, + Some(r##"The ID of the annotation data to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"content-version"##), + None, + Some(r##"The content version for the volume you are trying to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("annotation-data-list", + Some(r##"Gets the annotation data for a volume and layer."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/layers_annotation-data-list", + vec![ + (Some(r##"volume-id"##), + None, + Some(r##"The volume to retrieve annotation data for."##), + Some(true), + Some(false)), + + (Some(r##"layer-id"##), + None, + Some(r##"The ID for the layer to get the annotation data."##), + Some(true), + Some(false)), + + (Some(r##"content-version"##), + None, + Some(r##"The content version for the requested volume."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Gets the layer summary for a volume."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/layers_get", + vec![ + (Some(r##"volume-id"##), + None, + Some(r##"The volume to retrieve layers for."##), + Some(true), + Some(false)), + + (Some(r##"summary-id"##), + None, + Some(r##"The ID for the layer to get the summary for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List the layer summaries for a volume."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/layers_list", + vec![ + (Some(r##"volume-id"##), + None, + Some(r##"The volume to retrieve layers for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("volume-annotations-get", + Some(r##"Gets the volume annotation."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/layers_volume-annotations-get", + vec![ + (Some(r##"volume-id"##), + None, + Some(r##"The volume to retrieve annotations for."##), + Some(true), + Some(false)), + + (Some(r##"layer-id"##), + None, + Some(r##"The ID for the layer to get the annotations."##), + Some(true), + Some(false)), + + (Some(r##"annotation-id"##), + None, + Some(r##"The ID of the volume annotation to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("volume-annotations-list", + Some(r##"Gets the volume annotations for a volume and layer."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/layers_volume-annotations-list", + vec![ + (Some(r##"volume-id"##), + None, + Some(r##"The volume to retrieve annotations for."##), + Some(true), + Some(false)), + + (Some(r##"layer-id"##), + None, + Some(r##"The ID for the layer to get the annotations."##), + Some(true), + Some(false)), + + (Some(r##"content-version"##), + None, + Some(r##"The content version for the requested volume."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("myconfig", "methods: 'get-user-settings', 'release-download-access', 'request-access', 'sync-volume-licenses' and 'update-user-settings'", vec![ + ("get-user-settings", + Some(r##"Gets the current settings for the user."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/myconfig_get-user-settings", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("release-download-access", + Some(r##"Release downloaded content access restriction."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/myconfig_release-download-access", + vec![ + (Some(r##"volume-ids"##), + None, + Some(r##"The volume(s) to release restrictions for."##), + Some(true), + Some(false)), + + (Some(r##"cpksver"##), + None, + Some(r##"The device/version ID from which to release the restriction."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("request-access", + Some(r##"Request concurrent and download access restrictions."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/myconfig_request-access", + vec![ + (Some(r##"source"##), + None, + Some(r##"String to identify the originator of this request."##), + Some(true), + Some(false)), + + (Some(r##"volume-id"##), + None, + Some(r##"The volume to request concurrent/download restrictions for."##), + Some(true), + Some(false)), + + (Some(r##"nonce"##), + None, + Some(r##"The client nonce value."##), + Some(true), + Some(false)), + + (Some(r##"cpksver"##), + None, + Some(r##"The device/version ID from which to request the restrictions."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("sync-volume-licenses", + Some(r##"Request downloaded content access for specified volumes on the My eBooks shelf."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/myconfig_sync-volume-licenses", + vec![ + (Some(r##"source"##), + None, + Some(r##"String to identify the originator of this request."##), + Some(true), + Some(false)), + + (Some(r##"nonce"##), + None, + Some(r##"The client nonce value."##), + Some(true), + Some(false)), + + (Some(r##"cpksver"##), + None, + Some(r##"The device/version ID from which to release the restriction."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update-user-settings", + Some(r##"Sets the settings for the user. If a sub-object is specified, it will overwrite the existing sub-object stored in the server. Unspecified sub-objects will retain the existing value."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/myconfig_update-user-settings", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("mylibrary", "methods: 'annotations-delete', 'annotations-insert', 'annotations-list', 'annotations-summary', 'annotations-update', 'bookshelves-add-volume', 'bookshelves-clear-volumes', 'bookshelves-get', 'bookshelves-list', 'bookshelves-move-volume', 'bookshelves-remove-volume', 'bookshelves-volumes-list', 'readingpositions-get' and 'readingpositions-set-position'", vec![ + ("annotations-delete", + Some(r##"Deletes an annotation."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/mylibrary_annotations-delete", + vec![ + (Some(r##"annotation-id"##), + None, + Some(r##"The ID for the annotation to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("annotations-insert", + Some(r##"Inserts a new annotation."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/mylibrary_annotations-insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("annotations-list", + Some(r##"Retrieves a list of annotations, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/mylibrary_annotations-list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("annotations-summary", + Some(r##"Gets the summary of specified layers."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/mylibrary_annotations-summary", + vec![ + (Some(r##"layer-ids"##), + None, + Some(r##"Array of layer IDs to get the summary for."##), + Some(true), + Some(false)), + + (Some(r##"volume-id"##), + None, + Some(r##"Volume id to get the summary for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("annotations-update", + Some(r##"Updates an existing annotation."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/mylibrary_annotations-update", + vec![ + (Some(r##"annotation-id"##), + None, + Some(r##"The ID for the annotation to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("bookshelves-add-volume", + Some(r##"Adds a volume to a bookshelf."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/mylibrary_bookshelves-add-volume", + vec![ + (Some(r##"shelf"##), + None, + Some(r##"ID of bookshelf to which to add a volume."##), + Some(true), + Some(false)), + + (Some(r##"volume-id"##), + None, + Some(r##"ID of volume to add."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("bookshelves-clear-volumes", + Some(r##"Clears all volumes from a bookshelf."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/mylibrary_bookshelves-clear-volumes", + vec![ + (Some(r##"shelf"##), + None, + Some(r##"ID of bookshelf from which to remove a volume."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("bookshelves-get", + Some(r##"Retrieves metadata for a specific bookshelf belonging to the authenticated user."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/mylibrary_bookshelves-get", + vec![ + (Some(r##"shelf"##), + None, + Some(r##"ID of bookshelf to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("bookshelves-list", + Some(r##"Retrieves a list of bookshelves belonging to the authenticated user."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/mylibrary_bookshelves-list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("bookshelves-move-volume", + Some(r##"Moves a volume within a bookshelf."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/mylibrary_bookshelves-move-volume", + vec![ + (Some(r##"shelf"##), + None, + Some(r##"ID of bookshelf with the volume."##), + Some(true), + Some(false)), + + (Some(r##"volume-id"##), + None, + Some(r##"ID of volume to move."##), + Some(true), + Some(false)), + + (Some(r##"volume-position"##), + None, + Some(r##"Position on shelf to move the item (0 puts the item before the current first item, 1 puts it between the first and the second and so on.)"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("bookshelves-remove-volume", + Some(r##"Removes a volume from a bookshelf."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/mylibrary_bookshelves-remove-volume", + vec![ + (Some(r##"shelf"##), + None, + Some(r##"ID of bookshelf from which to remove a volume."##), + Some(true), + Some(false)), + + (Some(r##"volume-id"##), + None, + Some(r##"ID of volume to remove."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("bookshelves-volumes-list", + Some(r##"Gets volume information for volumes on a bookshelf."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/mylibrary_bookshelves-volumes-list", + vec![ + (Some(r##"shelf"##), + None, + Some(r##"The bookshelf ID or name retrieve volumes for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("readingpositions-get", + Some(r##"Retrieves my reading position information for a volume."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/mylibrary_readingpositions-get", + vec![ + (Some(r##"volume-id"##), + None, + Some(r##"ID of volume for which to retrieve a reading position."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("readingpositions-set-position", + Some(r##"Sets my reading position information for a volume."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/mylibrary_readingpositions-set-position", + vec![ + (Some(r##"volume-id"##), + None, + Some(r##"ID of volume for which to update the reading position."##), + Some(true), + Some(false)), + + (Some(r##"timestamp"##), + None, + Some(r##"RFC 3339 UTC format timestamp associated with this reading position."##), + Some(true), + Some(false)), + + (Some(r##"position"##), + None, + Some(r##"Position string for the new volume reading position."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("onboarding", "methods: 'list-categories' and 'list-category-volumes'", vec![ + ("list-categories", + Some(r##"List categories for onboarding experience."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/onboarding_list-categories", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-category-volumes", + Some(r##"List available volumes under categories for onboarding experience."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/onboarding_list-category-volumes", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("promooffer", "methods: 'accept', 'dismiss' and 'get'", vec![ + ("accept", + Some(r##""##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/promooffer_accept", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("dismiss", + Some(r##""##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/promooffer_dismiss", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Returns a list of promo offers available to the user"##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/promooffer_get", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("volumes", "methods: 'associated-list', 'get', 'list', 'mybooks-list', 'recommended-list', 'recommended-rate' and 'useruploaded-list'", vec![ + ("associated-list", + Some(r##"Return a list of associated books."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/volumes_associated-list", + vec![ + (Some(r##"volume-id"##), + None, + Some(r##"ID of the source volume."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Gets volume information for a single volume."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/volumes_get", + vec![ + (Some(r##"volume-id"##), + None, + Some(r##"ID of volume to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Performs a book search."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/volumes_list", + vec![ + (Some(r##"q"##), + None, + Some(r##"Full-text search query string."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("mybooks-list", + Some(r##"Return a list of books in My Library."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/volumes_mybooks-list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("recommended-list", + Some(r##"Return a list of recommended books for the current user."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/volumes_recommended-list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("recommended-rate", + Some(r##"Rate a recommended book for the current user."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/volumes_recommended-rate", + vec![ + (Some(r##"rating"##), + None, + Some(r##"Rating to be given to the volume."##), + Some(true), + Some(false)), + + (Some(r##"volume-id"##), + None, + Some(r##"ID of the source volume."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("useruploaded-list", + Some(r##"Return a list of books uploaded by the current user."##), + "Details at http://byron.github.io/google-apis-rs/google_books1_cli/volumes_useruploaded-list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("books1") + .author("Sebastian Thiel ") + .version("0.2.0+20150401") + .about("Lets you search for books and manage your Google Books library.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_books1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/books1/Cargo.toml b/gen/books1/Cargo.toml index d9a7f62792..33f7a0207f 100644 --- a/gen/books1/Cargo.toml +++ b/gen/books1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-books1" -version = "0.1.6+20150401" +version = "0.1.7+20150401" authors = ["Sebastian Thiel "] description = "A complete library to interact with books (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/books1" @@ -15,9 +15,10 @@ keywords = ["books", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/books1/README.md b/gen/books1/README.md index de570fb159..da7a233f41 100644 --- a/gen/books1/README.md +++ b/gen/books1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-books1` library allows access to all features of the *Google books* service. -This documentation was generated from *books* crate version *0.1.6+20150401*, where *20150401* is the exact revision of the *books:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *books* crate version *0.1.7+20150401*, where *20150401* is the exact revision of the *books:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *books* *v1* API can be found at the [official documentation site](https://developers.google.com/books/docs/v1/getting_started). @@ -192,7 +192,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_books1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_books1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/books1/src/cmn.rs b/gen/books1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/books1/src/cmn.rs +++ b/gen/books1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/books1/src/lib.rs b/gen/books1/src/lib.rs index 3246c9ce23..d50b83c85a 100644 --- a/gen/books1/src/lib.rs +++ b/gen/books1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *books* crate version *0.1.6+20150401*, where *20150401* is the exact revision of the *books:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *books* crate version *0.1.7+20150401*, where *20150401* is the exact revision of the *books:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *books* *v1* API can be found at the //! [official documentation site](https://developers.google.com/books/docs/v1/getting_started). @@ -193,7 +193,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -202,7 +202,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -218,6 +217,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -346,7 +346,7 @@ impl<'a, C, A> Books Books { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -379,7 +379,7 @@ impl<'a, C, A> Books } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -3444,7 +3444,7 @@ impl<'a, C, A> LayerAnnotationDataGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3466,7 +3466,7 @@ impl<'a, C, A> LayerAnnotationDataGetCall<'a, C, A> where C: BorrowMut LayerVolumeAnnotationGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3791,7 +3791,7 @@ impl<'a, C, A> LayerVolumeAnnotationGetCall<'a, C, A> where C: BorrowMut LayerListCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4084,7 +4084,7 @@ impl<'a, C, A> LayerListCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4341,7 +4341,7 @@ impl<'a, C, A> LayerGetCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4363,7 +4363,7 @@ impl<'a, C, A> LayerGetCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4668,7 +4668,7 @@ impl<'a, C, A> LayerVolumeAnnotationListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4690,7 +4690,7 @@ impl<'a, C, A> LayerVolumeAnnotationListCall<'a, C, A> where C: BorrowMut LayerAnnotationDataListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5091,7 +5091,7 @@ impl<'a, C, A> LayerAnnotationDataListCall<'a, C, A> where C: BorrowMut VolumeRecommendedRateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5409,7 +5409,7 @@ impl<'a, C, A> VolumeRecommendedRateCall<'a, C, A> where C: BorrowMut VolumeMybookListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5684,7 +5684,7 @@ impl<'a, C, A> VolumeMybookListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5971,7 +5971,7 @@ impl<'a, C, A> VolumeListCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5993,7 +5993,7 @@ impl<'a, C, A> VolumeListCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6306,7 +6306,7 @@ impl<'a, C, A> VolumeUseruploadedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6328,7 +6328,7 @@ impl<'a, C, A> VolumeUseruploadedListCall<'a, C, A> where C: BorrowMut VolumeAssociatedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6616,7 +6616,7 @@ impl<'a, C, A> VolumeAssociatedListCall<'a, C, A> where C: BorrowMut VolumeGetCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6901,7 +6901,7 @@ impl<'a, C, A> VolumeGetCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7136,7 +7136,7 @@ impl<'a, C, A> VolumeRecommendedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7158,7 +7158,7 @@ impl<'a, C, A> VolumeRecommendedListCall<'a, C, A> where C: BorrowMut DictionaryListOfflineMetadataCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7377,7 +7377,7 @@ impl<'a, C, A> DictionaryListOfflineMetadataCall<'a, C, A> where C: BorrowMut BookshelveVolumeListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7638,7 +7638,7 @@ impl<'a, C, A> BookshelveVolumeListCall<'a, C, A> where C: BorrowMut BookshelveListCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7920,7 +7920,7 @@ impl<'a, C, A> BookshelveListCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8151,7 +8151,7 @@ impl<'a, C, A> BookshelveGetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8173,7 +8173,7 @@ impl<'a, C, A> BookshelveGetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8420,7 +8420,7 @@ impl<'a, C, A> PromoofferAcceptCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8442,7 +8442,7 @@ impl<'a, C, A> PromoofferAcceptCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8702,7 +8702,7 @@ impl<'a, C, A> PromoofferDismisCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8724,7 +8724,7 @@ impl<'a, C, A> PromoofferDismisCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8974,7 +8974,7 @@ impl<'a, C, A> PromoofferGetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8996,7 +8996,7 @@ impl<'a, C, A> PromoofferGetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9224,7 +9224,7 @@ impl<'a, C, A> OnboardingListCategoryCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9246,7 +9246,7 @@ impl<'a, C, A> OnboardingListCategoryCall<'a, C, A> where C: BorrowMut OnboardingListCategoryVolumeCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9480,7 +9480,7 @@ impl<'a, C, A> OnboardingListCategoryVolumeCall<'a, C, A> where C: BorrowMut MyconfigRequestAccesCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9730,7 +9730,7 @@ impl<'a, C, A> MyconfigRequestAccesCall<'a, C, A> where C: BorrowMut MyconfigReleaseDownloadAccesCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10007,7 +10007,7 @@ impl<'a, C, A> MyconfigReleaseDownloadAccesCall<'a, C, A> where C: BorrowMut MyconfigSyncVolumeLicenseCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10279,7 +10279,7 @@ impl<'a, C, A> MyconfigSyncVolumeLicenseCall<'a, C, A> where C: BorrowMut MyconfigGetUserSettingCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10542,7 +10542,7 @@ impl<'a, C, A> MyconfigGetUserSettingCall<'a, C, A> where C: BorrowMut MyconfigUpdateUserSettingCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Usersettings)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10730,11 +10731,20 @@ impl<'a, C, A> MyconfigUpdateUserSettingCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10757,7 +10767,7 @@ impl<'a, C, A> MyconfigUpdateUserSettingCall<'a, C, A> where C: BorrowMut MylibraryBookshelveClearVolumeCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11002,7 +11012,7 @@ impl<'a, C, A> MylibraryBookshelveClearVolumeCall<'a, C, A> where C: BorrowMut MylibraryBookshelveMoveVolumeCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11246,7 +11256,7 @@ impl<'a, C, A> MylibraryBookshelveMoveVolumeCall<'a, C, A> where C: BorrowMut MylibraryBookshelveVolumeListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11537,7 +11547,7 @@ impl<'a, C, A> MylibraryBookshelveVolumeListCall<'a, C, A> where C: BorrowMut MylibraryAnnotationSummaryCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11809,7 +11819,7 @@ impl<'a, C, A> MylibraryAnnotationSummaryCall<'a, C, A> where C: BorrowMut MylibraryAnnotationDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12063,7 +12073,7 @@ impl<'a, C, A> MylibraryAnnotationDeleteCall<'a, C, A> where C: BorrowMut MylibraryBookshelveAddVolumeCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12310,7 +12320,7 @@ impl<'a, C, A> MylibraryBookshelveAddVolumeCall<'a, C, A> where C: BorrowMut MylibraryAnnotationInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Annotation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12537,11 +12548,20 @@ impl<'a, C, A> MylibraryAnnotationInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12564,7 +12584,7 @@ impl<'a, C, A> MylibraryAnnotationInsertCall<'a, C, A> where C: BorrowMut MylibraryBookshelveRemoveVolumeCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12837,7 +12857,7 @@ impl<'a, C, A> MylibraryBookshelveRemoveVolumeCall<'a, C, A> where C: BorrowMut< access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -13096,7 +13116,7 @@ impl<'a, C, A> MylibraryAnnotationListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13118,7 +13138,7 @@ impl<'a, C, A> MylibraryAnnotationListCall<'a, C, A> where C: BorrowMut MylibraryAnnotationUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Annotation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13408,11 +13429,20 @@ impl<'a, C, A> MylibraryAnnotationUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13435,7 +13465,7 @@ impl<'a, C, A> MylibraryAnnotationUpdateCall<'a, C, A> where C: BorrowMut MylibraryReadingpositionSetPositionCall<'a, C, A> where C: Borrow if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13716,7 +13746,7 @@ impl<'a, C, A> MylibraryReadingpositionSetPositionCall<'a, C, A> where C: Borrow access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -13976,7 +14006,7 @@ impl<'a, C, A> MylibraryBookshelveGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13998,7 +14028,7 @@ impl<'a, C, A> MylibraryBookshelveGetCall<'a, C, A> where C: BorrowMut MylibraryBookshelveListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14223,7 +14253,7 @@ impl<'a, C, A> MylibraryBookshelveListCall<'a, C, A> where C: BorrowMut MylibraryReadingpositionGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14469,7 +14499,7 @@ impl<'a, C, A> MylibraryReadingpositionGetCall<'a, C, A> where C: BorrowMut CloudloadingAddBookCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14716,7 +14746,7 @@ impl<'a, C, A> CloudloadingAddBookCall<'a, C, A> where C: BorrowMut CloudloadingUpdateBookCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, BooksCloudloadingResource)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14931,11 +14962,20 @@ impl<'a, C, A> CloudloadingUpdateBookCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14958,7 +14998,7 @@ impl<'a, C, A> CloudloadingUpdateBookCall<'a, C, A> where C: BorrowMut CloudloadingDeleteBookCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15174,7 +15214,7 @@ impl<'a, C, A> CloudloadingDeleteBookCall<'a, C, A> where C: BorrowMut"] description = "A complete library to interact with calendar (protocol v3)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/calendar3-cli" @@ -17,15 +17,14 @@ keywords = ["calendar", "google", "cli"] name = "calendar3" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-calendar3] path = "../calendar3" diff --git a/gen/calendar3-cli/README.md b/gen/calendar3-cli/README.md index 3f622a7248..6906f69ad8 100644 --- a/gen/calendar3-cli/README.md +++ b/gen/calendar3-cli/README.md @@ -10,57 +10,66 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *calendar* API can be found at the +[official documentation site](https://developers.google.com/google-apps/calendar/firstapp). + # Usage -This documentation was generated from the *calendar* API at revision *20150326*. The CLI is at version *0.1.0*. +This documentation was generated from the *calendar* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - calendar3 [options] acl delete [-p ...] - calendar3 [options] acl get [-p ...] [-o ] - calendar3 [options] acl insert -r ... [-p ...] [-o ] - calendar3 [options] acl list [-p ...] [-o ] - calendar3 [options] acl patch -r ... [-p ...] [-o ] - calendar3 [options] acl update -r ... [-p ...] [-o ] - calendar3 [options] acl watch -r ... [-p ...] [-o ] - calendar3 [options] calendar-list delete [-p ...] - calendar3 [options] calendar-list get [-p ...] [-o ] - calendar3 [options] calendar-list insert -r ... [-p ...] [-o ] - calendar3 [options] calendar-list list [-p ...] [-o ] - calendar3 [options] calendar-list patch -r ... [-p ...] [-o ] - calendar3 [options] calendar-list update -r ... [-p ...] [-o ] - calendar3 [options] calendar-list watch -r ... [-p ...] [-o ] - calendar3 [options] calendars clear [-p ...] - calendar3 [options] calendars delete [-p ...] - calendar3 [options] calendars get [-p ...] [-o ] - calendar3 [options] calendars insert -r ... [-p ...] [-o ] - calendar3 [options] calendars patch -r ... [-p ...] [-o ] - calendar3 [options] calendars update -r ... [-p ...] [-o ] - calendar3 [options] channels stop -r ... [-p ...] - calendar3 [options] colors get [-p ...] [-o ] - calendar3 [options] events delete [-p ...] - calendar3 [options] events get [-p ...] [-o ] - calendar3 [options] events import -r ... [-p ...] [-o ] - calendar3 [options] events insert -r ... [-p ...] [-o ] - calendar3 [options] events instances [-p ...] [-o ] - calendar3 [options] events list [-p ...] [-o ] - calendar3 [options] events move [-p ...] [-o ] - calendar3 [options] events patch -r ... [-p ...] [-o ] - calendar3 [options] events quick-add [-p ...] [-o ] - calendar3 [options] events update -r ... [-p ...] [-o ] - calendar3 [options] events watch -r ... [-p ...] [-o ] - calendar3 [options] freebusy query -r ... [-p ...] [-o ] - calendar3 [options] settings get [-p ...] [-o ] - calendar3 [options] settings list [-p ...] [-o ] - calendar3 [options] settings watch -r ... [-p ...] [-o ] +calendar3 [options] + acl + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + watch (-r )... [-p ]... [-o ] + calendar-list + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + watch (-r )... [-p ]... [-o ] + calendars + clear [-p ]... + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + channels + stop (-r )... [-p ]... + colors + get [-p ]... [-o ] + events + delete [-p ]... + get [-p ]... [-o ] + import (-r )... [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + instances [-p ]... [-o ] + list [-p ]... [-o ] + move [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + quick-add [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + watch (-r )... [-p ]... [-o ] + freebusy + query (-r )... [-p ]... [-o ] + settings + get [-p ]... [-o ] + list [-p ]... [-o ] + watch (-r )... [-p ]... [-o ] calendar3 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_calendar3_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/calendar3-cli/mkdocs.yml b/gen/calendar3-cli/mkdocs.yml index 07397ee0ed..26a0c93b05 100644 --- a/gen/calendar3-cli/mkdocs.yml +++ b/gen/calendar3-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: calendar v0.1.0+20150326 +site_name: calendar v0.2.0+20150326 site_url: http://byron.github.io/google-apis-rs/google-calendar3-cli site_description: Write integrating applications with bcore diff --git a/gen/calendar3-cli/src/cmn.rs b/gen/calendar3-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/calendar3-cli/src/cmn.rs +++ b/gen/calendar3-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/calendar3-cli/src/main.rs b/gen/calendar3-cli/src/main.rs index 1bbd96128a..9796b5d0a0 100644 --- a/gen/calendar3-cli/src/main.rs +++ b/gen/calendar3-cli/src/main.rs @@ -2,195 +2,148 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_calendar3 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - calendar3 [options] acl delete [-p ...] - calendar3 [options] acl get [-p ...] [-o ] - calendar3 [options] acl insert -r ... [-p ...] [-o ] - calendar3 [options] acl list [-p ...] [-o ] - calendar3 [options] acl patch -r ... [-p ...] [-o ] - calendar3 [options] acl update -r ... [-p ...] [-o ] - calendar3 [options] acl watch -r ... [-p ...] [-o ] - calendar3 [options] calendar-list delete [-p ...] - calendar3 [options] calendar-list get [-p ...] [-o ] - calendar3 [options] calendar-list insert -r ... [-p ...] [-o ] - calendar3 [options] calendar-list list [-p ...] [-o ] - calendar3 [options] calendar-list patch -r ... [-p ...] [-o ] - calendar3 [options] calendar-list update -r ... [-p ...] [-o ] - calendar3 [options] calendar-list watch -r ... [-p ...] [-o ] - calendar3 [options] calendars clear [-p ...] - calendar3 [options] calendars delete [-p ...] - calendar3 [options] calendars get [-p ...] [-o ] - calendar3 [options] calendars insert -r ... [-p ...] [-o ] - calendar3 [options] calendars patch -r ... [-p ...] [-o ] - calendar3 [options] calendars update -r ... [-p ...] [-o ] - calendar3 [options] channels stop -r ... [-p ...] - calendar3 [options] colors get [-p ...] [-o ] - calendar3 [options] events delete [-p ...] - calendar3 [options] events get [-p ...] [-o ] - calendar3 [options] events import -r ... [-p ...] [-o ] - calendar3 [options] events insert -r ... [-p ...] [-o ] - calendar3 [options] events instances [-p ...] [-o ] - calendar3 [options] events list [-p ...] [-o ] - calendar3 [options] events move [-p ...] [-o ] - calendar3 [options] events patch -r ... [-p ...] [-o ] - calendar3 [options] events quick-add [-p ...] [-o ] - calendar3 [options] events update -r ... [-p ...] [-o ] - calendar3 [options] events watch -r ... [-p ...] [-o ] - calendar3 [options] freebusy query -r ... [-p ...] [-o ] - calendar3 [options] settings get [-p ...] [-o ] - calendar3 [options] settings list [-p ...] [-o ] - calendar3 [options] settings watch -r ... [-p ...] [-o ] - calendar3 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_calendar3_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::CalendarHub>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _acl_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.acl().delete(&self.opt.arg_calendar_id, &self.opt.arg_rule_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _acl_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.acl().delete(opt.value_of("calendar-id").unwrap_or(""), opt.value_of("rule-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _acl_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.acl().get(&self.opt.arg_calendar_id, &self.opt.arg_rule_id); - for parg in self.opt.arg_v.iter() { + fn _acl_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.acl().get(opt.value_of("calendar-id").unwrap_or(""), opt.value_of("rule-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _acl_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _acl_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AclRule::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -236,58 +189,63 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "id", "kind", "role", "scope", "type", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.acl().insert(request, &self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.acl().insert(request, opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _acl_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.acl().list(&self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + fn _acl_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.acl().list(opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "sync-token" => { @@ -302,52 +260,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sync-token", "max-results", "page-token", "show-deleted"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _acl_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _acl_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AclRule::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -393,60 +355,65 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "id", "kind", "role", "scope", "type", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.acl().patch(request, &self.opt.arg_calendar_id, &self.opt.arg_rule_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.acl().patch(request, opt.value_of("calendar-id").unwrap_or(""), opt.value_of("rule-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _acl_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _acl_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AclRule::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -492,60 +459,65 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "id", "kind", "role", "scope", "type", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.acl().update(request, &self.opt.arg_calendar_id, &self.opt.arg_rule_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.acl().update(request, opt.value_of("calendar-id").unwrap_or(""), opt.value_of("rule-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _acl_watch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _acl_watch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Channel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -595,12 +567,13 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.acl().watch(request, &self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.acl().watch(request, opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "sync-token" => { @@ -615,142 +588,149 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sync-token", "max-results", "page-token", "show-deleted"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _calendar_list_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.calendar_list().delete(&self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + fn _calendar_list_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.calendar_list().delete(opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _calendar_list_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.calendar_list().get(&self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + fn _calendar_list_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.calendar_list().get(opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _calendar_list_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _calendar_list_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CalendarListEntry::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -814,61 +794,66 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["access-role", "background-color", "color-id", "deleted", "description", "etag", "foreground-color", "hidden", "id", "kind", "location", "primary", "selected", "summary", "summary-override", "time-zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.calendar_list().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "color-rgb-format" => { call = call.color_rgb_format(arg_from_str(value.unwrap_or("false"), err, "color-rgb-format", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["color-rgb-format"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _calendar_list_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _calendar_list_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.calendar_list().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "sync-token" => { @@ -889,52 +874,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sync-token", "min-access-role", "show-deleted", "max-results", "page-token", "show-hidden"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _calendar_list_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _calendar_list_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CalendarListEntry::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -998,63 +987,68 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["access-role", "background-color", "color-id", "deleted", "description", "etag", "foreground-color", "hidden", "id", "kind", "location", "primary", "selected", "summary", "summary-override", "time-zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.calendar_list().patch(request, &self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.calendar_list().patch(request, opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "color-rgb-format" => { call = call.color_rgb_format(arg_from_str(value.unwrap_or("false"), err, "color-rgb-format", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["color-rgb-format"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _calendar_list_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _calendar_list_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CalendarListEntry::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1118,63 +1112,68 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["access-role", "background-color", "color-id", "deleted", "description", "etag", "foreground-color", "hidden", "id", "kind", "location", "primary", "selected", "summary", "summary-override", "time-zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.calendar_list().update(request, &self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.calendar_list().update(request, opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "color-rgb-format" => { call = call.color_rgb_format(arg_from_str(value.unwrap_or("false"), err, "color-rgb-format", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["color-rgb-format"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _calendar_list_watch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _calendar_list_watch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Channel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1224,12 +1223,13 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.calendar_list().watch(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "sync-token" => { @@ -1250,186 +1250,192 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sync-token", "min-access-role", "show-deleted", "max-results", "page-token", "show-hidden"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _calendars_clear(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.calendars().clear(&self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + fn _calendars_clear(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.calendars().clear(opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _calendars_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.calendars().delete(&self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + fn _calendars_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.calendars().delete(opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _calendars_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.calendars().get(&self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + fn _calendars_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.calendars().get(opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _calendars_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _calendars_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Calendar::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1466,60 +1472,65 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["description", "etag", "id", "kind", "location", "summary", "time-zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.calendars().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _calendars_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _calendars_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Calendar::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1556,60 +1567,65 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["description", "etag", "id", "kind", "location", "summary", "time-zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.calendars().patch(request, &self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.calendars().patch(request, opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _calendars_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _calendars_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Calendar::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1646,60 +1662,65 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["description", "etag", "id", "kind", "location", "summary", "time-zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.calendars().update(request, &self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.calendars().update(request, opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _channels_stop(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _channels_stop(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Channel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1749,149 +1770,152 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.channels().stop(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _colors_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _colors_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.colors().get(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _events_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.events().delete(&self.opt.arg_calendar_id, &self.opt.arg_event_id); - for parg in self.opt.arg_v.iter() { + fn _events_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.events().delete(opt.value_of("calendar-id").unwrap_or(""), opt.value_of("event-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "send-notifications" => { call = call.send_notifications(arg_from_str(value.unwrap_or("false"), err, "send-notifications", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["send-notifications"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _events_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.events().get(&self.opt.arg_calendar_id, &self.opt.arg_event_id); - for parg in self.opt.arg_v.iter() { + fn _events_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.events().get(opt.value_of("calendar-id").unwrap_or(""), opt.value_of("event-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "time-zone" => { @@ -1903,52 +1927,56 @@ impl Engine { "always-include-email" => { call = call.always_include_email(arg_from_str(value.unwrap_or("false"), err, "always-include-email", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["time-zone", "always-include-email", "max-attendees"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _events_import(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _events_import(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Event::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2257,60 +2285,65 @@ impl Engine { request.private_copy = Some(arg_from_str(value.unwrap_or("false"), err, "private-copy", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["anyone-can-add-self", "attendees-omitted", "color-id", "created", "creator", "date", "date-time", "description", "display", "display-name", "email", "end", "end-time-unspecified", "etag", "extended-properties", "gadget", "guests-can-invite-others", "guests-can-modify", "guests-can-see-other-guests", "hangout-link", "height", "html-link", "i-cal-uid", "icon-link", "id", "kind", "link", "location", "locked", "organizer", "original-start-time", "preferences", "private", "private-copy", "recurrence", "recurring-event-id", "reminders", "self", "sequence", "shared", "source", "start", "status", "summary", "time-zone", "title", "transparency", "type", "updated", "url", "use-default", "visibility", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.events().import(request, &self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.events().import(request, opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _events_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _events_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Event::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2619,12 +2652,13 @@ impl Engine { request.private_copy = Some(arg_from_str(value.unwrap_or("false"), err, "private-copy", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["anyone-can-add-self", "attendees-omitted", "color-id", "created", "creator", "date", "date-time", "description", "display", "display-name", "email", "end", "end-time-unspecified", "etag", "extended-properties", "gadget", "guests-can-invite-others", "guests-can-modify", "guests-can-see-other-guests", "hangout-link", "height", "html-link", "i-cal-uid", "icon-link", "id", "kind", "link", "location", "locked", "organizer", "original-start-time", "preferences", "private", "private-copy", "recurrence", "recurring-event-id", "reminders", "self", "sequence", "shared", "source", "start", "status", "summary", "time-zone", "title", "transparency", "type", "updated", "url", "use-default", "visibility", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.events().insert(request, &self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.events().insert(request, opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "send-notifications" => { @@ -2633,50 +2667,54 @@ impl Engine { "max-attendees" => { call = call.max_attendees(arg_from_str(value.unwrap_or("-0"), err, "max-attendees", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["max-attendees", "send-notifications"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _events_instances(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.events().instances(&self.opt.arg_calendar_id, &self.opt.arg_event_id); - for parg in self.opt.arg_v.iter() { + fn _events_instances(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.events().instances(opt.value_of("calendar-id").unwrap_or(""), opt.value_of("event-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "time-zone" => { @@ -2706,50 +2744,54 @@ impl Engine { "always-include-email" => { call = call.always_include_email(arg_from_str(value.unwrap_or("false"), err, "always-include-email", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["show-deleted", "time-max", "always-include-email", "max-results", "page-token", "time-min", "time-zone", "original-start", "max-attendees"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _events_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.events().list(&self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + fn _events_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.events().list(opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "updated-min" => { @@ -2803,101 +2845,109 @@ impl Engine { "always-include-email" => { call = call.always_include_email(arg_from_str(value.unwrap_or("false"), err, "always-include-email", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["show-hidden-invitations", "sync-token", "page-token", "time-max", "updated-min", "single-events", "i-cal-uid", "always-include-email", "order-by", "q", "show-deleted", "max-results", "time-min", "time-zone", "private-extended-property", "shared-extended-property", "max-attendees"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _events_move(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.events().move_(&self.opt.arg_calendar_id, &self.opt.arg_event_id, &self.opt.arg_destination); - for parg in self.opt.arg_v.iter() { + fn _events_move(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.events().move_(opt.value_of("calendar-id").unwrap_or(""), opt.value_of("event-id").unwrap_or(""), opt.value_of("destination").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "send-notifications" => { call = call.send_notifications(arg_from_str(value.unwrap_or("false"), err, "send-notifications", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["send-notifications"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _events_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _events_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Event::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3206,12 +3256,13 @@ impl Engine { request.private_copy = Some(arg_from_str(value.unwrap_or("false"), err, "private-copy", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["anyone-can-add-self", "attendees-omitted", "color-id", "created", "creator", "date", "date-time", "description", "display", "display-name", "email", "end", "end-time-unspecified", "etag", "extended-properties", "gadget", "guests-can-invite-others", "guests-can-modify", "guests-can-see-other-guests", "hangout-link", "height", "html-link", "i-cal-uid", "icon-link", "id", "kind", "link", "location", "locked", "organizer", "original-start-time", "preferences", "private", "private-copy", "recurrence", "recurring-event-id", "reminders", "self", "sequence", "shared", "source", "start", "status", "summary", "time-zone", "title", "transparency", "type", "updated", "url", "use-default", "visibility", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.events().patch(request, &self.opt.arg_calendar_id, &self.opt.arg_event_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.events().patch(request, opt.value_of("calendar-id").unwrap_or(""), opt.value_of("event-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "send-notifications" => { @@ -3223,101 +3274,109 @@ impl Engine { "always-include-email" => { call = call.always_include_email(arg_from_str(value.unwrap_or("false"), err, "always-include-email", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["max-attendees", "always-include-email", "send-notifications"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _events_quick_add(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.events().quick_add(&self.opt.arg_calendar_id, &self.opt.arg_text); - for parg in self.opt.arg_v.iter() { + fn _events_quick_add(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.events().quick_add(opt.value_of("calendar-id").unwrap_or(""), opt.value_of("text").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "send-notifications" => { call = call.send_notifications(arg_from_str(value.unwrap_or("false"), err, "send-notifications", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["send-notifications"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _events_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _events_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Event::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3626,12 +3685,13 @@ impl Engine { request.private_copy = Some(arg_from_str(value.unwrap_or("false"), err, "private-copy", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["anyone-can-add-self", "attendees-omitted", "color-id", "created", "creator", "date", "date-time", "description", "display", "display-name", "email", "end", "end-time-unspecified", "etag", "extended-properties", "gadget", "guests-can-invite-others", "guests-can-modify", "guests-can-see-other-guests", "hangout-link", "height", "html-link", "i-cal-uid", "icon-link", "id", "kind", "link", "location", "locked", "organizer", "original-start-time", "preferences", "private", "private-copy", "recurrence", "recurring-event-id", "reminders", "self", "sequence", "shared", "source", "start", "status", "summary", "time-zone", "title", "transparency", "type", "updated", "url", "use-default", "visibility", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.events().update(request, &self.opt.arg_calendar_id, &self.opt.arg_event_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.events().update(request, opt.value_of("calendar-id").unwrap_or(""), opt.value_of("event-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "send-notifications" => { @@ -3643,52 +3703,56 @@ impl Engine { "always-include-email" => { call = call.always_include_email(arg_from_str(value.unwrap_or("false"), err, "always-include-email", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["max-attendees", "always-include-email", "send-notifications"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _events_watch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _events_watch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Channel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3738,12 +3802,13 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.events().watch(request, &self.opt.arg_calendar_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.events().watch(request, opt.value_of("calendar-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "updated-min" => { @@ -3797,52 +3862,56 @@ impl Engine { "always-include-email" => { call = call.always_include_email(arg_from_str(value.unwrap_or("false"), err, "always-include-email", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["show-hidden-invitations", "sync-token", "page-token", "time-max", "updated-min", "single-events", "i-cal-uid", "always-include-email", "order-by", "q", "show-deleted", "max-results", "time-min", "time-zone", "private-extended-property", "shared-extended-property", "max-attendees"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _freebusy_query(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _freebusy_query(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::FreeBusyRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3873,104 +3942,113 @@ impl Engine { request.group_expansion_max = Some(arg_from_str(value.unwrap_or("-0"), err, "group-expansion-max", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["calendar-expansion-max", "group-expansion-max", "time-max", "time-min", "time-zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.freebusy().query(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _settings_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.settings().get(&self.opt.arg_setting); - for parg in self.opt.arg_v.iter() { + fn _settings_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.settings().get(opt.value_of("setting").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _settings_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _settings_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.settings().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "sync-token" => { @@ -3982,52 +4060,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sync-token", "max-results", "page-token"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _settings_watch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _settings_watch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Channel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4077,12 +4159,13 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.settings().watch(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "sync-token" => { @@ -4094,180 +4177,250 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sync-token", "max-results", "page-token"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_acl { - if self.opt.cmd_delete { - call_result = self._acl_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._acl_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._acl_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._acl_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._acl_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._acl_update(dry_run, &mut err); - } else if self.opt.cmd_watch { - call_result = self._acl_watch(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("acl", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._acl_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._acl_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._acl_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._acl_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._acl_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._acl_update(opt, dry_run, &mut err); + }, + ("watch", Some(opt)) => { + call_result = self._acl_watch(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("acl".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("calendar-list", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._calendar_list_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._calendar_list_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._calendar_list_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._calendar_list_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._calendar_list_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._calendar_list_update(opt, dry_run, &mut err); + }, + ("watch", Some(opt)) => { + call_result = self._calendar_list_watch(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("calendar-list".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("calendars", Some(opt)) => { + match opt.subcommand() { + ("clear", Some(opt)) => { + call_result = self._calendars_clear(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._calendars_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._calendars_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._calendars_insert(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._calendars_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._calendars_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("calendars".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("channels", Some(opt)) => { + match opt.subcommand() { + ("stop", Some(opt)) => { + call_result = self._channels_stop(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("channels".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("colors", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._colors_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("colors".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("events", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._events_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._events_get(opt, dry_run, &mut err); + }, + ("import", Some(opt)) => { + call_result = self._events_import(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._events_insert(opt, dry_run, &mut err); + }, + ("instances", Some(opt)) => { + call_result = self._events_instances(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._events_list(opt, dry_run, &mut err); + }, + ("move", Some(opt)) => { + call_result = self._events_move(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._events_patch(opt, dry_run, &mut err); + }, + ("quick-add", Some(opt)) => { + call_result = self._events_quick_add(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._events_update(opt, dry_run, &mut err); + }, + ("watch", Some(opt)) => { + call_result = self._events_watch(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("events".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("freebusy", Some(opt)) => { + match opt.subcommand() { + ("query", Some(opt)) => { + call_result = self._freebusy_query(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("freebusy".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("settings", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._settings_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._settings_list(opt, dry_run, &mut err); + }, + ("watch", Some(opt)) => { + call_result = self._settings_watch(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("settings".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_calendar_list { - if self.opt.cmd_delete { - call_result = self._calendar_list_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._calendar_list_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._calendar_list_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._calendar_list_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._calendar_list_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._calendar_list_update(dry_run, &mut err); - } else if self.opt.cmd_watch { - call_result = self._calendar_list_watch(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_calendars { - if self.opt.cmd_clear { - call_result = self._calendars_clear(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._calendars_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._calendars_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._calendars_insert(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._calendars_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._calendars_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_channels { - if self.opt.cmd_stop { - call_result = self._channels_stop(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_colors { - if self.opt.cmd_get { - call_result = self._colors_get(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_events { - if self.opt.cmd_delete { - call_result = self._events_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._events_get(dry_run, &mut err); - } else if self.opt.cmd_import { - call_result = self._events_import(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._events_insert(dry_run, &mut err); - } else if self.opt.cmd_instances { - call_result = self._events_instances(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._events_list(dry_run, &mut err); - } else if self.opt.cmd_move { - call_result = self._events_move(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._events_patch(dry_run, &mut err); - } else if self.opt.cmd_quick_add { - call_result = self._events_quick_add(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._events_update(dry_run, &mut err); - } else if self.opt.cmd_watch { - call_result = self._events_watch(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_freebusy { - if self.opt.cmd_query { - call_result = self._freebusy_query(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_settings { - if self.opt.cmd_get { - call_result = self._settings_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._settings_list(dry_run, &mut err); - } else if self.opt.cmd_watch { - call_result = self._settings_watch(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -4280,7 +4433,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -4293,7 +4446,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -4303,37 +4456,1057 @@ impl Engine { let engine = Engine { opt: opt, hub: api::CalendarHub::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("acl", "methods: 'delete', 'get', 'insert', 'list', 'patch', 'update' and 'watch'", vec![ + ("delete", + Some(r##"Deletes an access control rule."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/acl_delete", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"rule-id"##), + None, + Some(r##"ACL rule identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Returns an access control rule."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/acl_get", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"rule-id"##), + None, + Some(r##"ACL rule identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates an access control rule."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/acl_insert", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Returns the rules in the access control list for the calendar."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/acl_list", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an access control rule. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/acl_patch", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"rule-id"##), + None, + Some(r##"ACL rule identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an access control rule."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/acl_update", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"rule-id"##), + None, + Some(r##"ACL rule identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("watch", + Some(r##"Watch for changes to ACL resources."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/acl_watch", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("calendar-list", "methods: 'delete', 'get', 'insert', 'list', 'patch', 'update' and 'watch'", vec![ + ("delete", + Some(r##"Deletes an entry on the user's calendar list."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/calendar-list_delete", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Returns an entry on the user's calendar list."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/calendar-list_get", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Adds an entry to the user's calendar list."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/calendar-list_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Returns entries on the user's calendar list."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/calendar-list_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an entry on the user's calendar list. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/calendar-list_patch", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an entry on the user's calendar list."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/calendar-list_update", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("watch", + Some(r##"Watch for changes to CalendarList resources."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/calendar-list_watch", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("calendars", "methods: 'clear', 'delete', 'get', 'insert', 'patch' and 'update'", vec![ + ("clear", + Some(r##"Clears a primary calendar. This operation deletes all events associated with the primary calendar of an account."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/calendars_clear", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("delete", + Some(r##"Deletes a secondary calendar. Use calendars.clear for clearing all events on primary calendars."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/calendars_delete", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Returns metadata for a calendar."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/calendars_get", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a secondary calendar."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/calendars_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates metadata for a calendar. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/calendars_patch", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates metadata for a calendar."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/calendars_update", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("channels", "methods: 'stop'", vec![ + ("stop", + Some(r##"Stop watching resources through this channel"##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/channels_stop", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("colors", "methods: 'get'", vec![ + ("get", + Some(r##"Returns the color definitions for calendars and events."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/colors_get", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("events", "methods: 'delete', 'get', 'import', 'insert', 'instances', 'list', 'move', 'patch', 'quick-add', 'update' and 'watch'", vec![ + ("delete", + Some(r##"Deletes an event."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/events_delete", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"event-id"##), + None, + Some(r##"Event identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Returns an event."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/events_get", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"event-id"##), + None, + Some(r##"Event identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("import", + Some(r##"Imports an event. This operation is used to add a private copy of an existing event to a calendar."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/events_import", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates an event."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/events_insert", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("instances", + Some(r##"Returns instances of the specified recurring event."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/events_instances", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"event-id"##), + None, + Some(r##"Recurring event identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Returns events on the specified calendar."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/events_list", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("move", + Some(r##"Moves an event to another calendar, i.e. changes an event's organizer."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/events_move", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier of the source calendar where the event currently is on."##), + Some(true), + Some(false)), + + (Some(r##"event-id"##), + None, + Some(r##"Event identifier."##), + Some(true), + Some(false)), + + (Some(r##"destination"##), + None, + Some(r##"Calendar identifier of the target calendar where the event is to be moved to."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an event. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/events_patch", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"event-id"##), + None, + Some(r##"Event identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("quick-add", + Some(r##"Creates an event based on a simple text string."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/events_quick-add", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"text"##), + None, + Some(r##"The text describing the event to be created."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an event."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/events_update", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"event-id"##), + None, + Some(r##"Event identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("watch", + Some(r##"Watch for changes to Events resources."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/events_watch", + vec![ + (Some(r##"calendar-id"##), + None, + Some(r##"Calendar identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("freebusy", "methods: 'query'", vec![ + ("query", + Some(r##"Returns free/busy information for a set of calendars."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/freebusy_query", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("settings", "methods: 'get', 'list' and 'watch'", vec![ + ("get", + Some(r##"Returns a single user setting."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/settings_get", + vec![ + (Some(r##"setting"##), + None, + Some(r##"The id of the user setting."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Returns all user settings for the authenticated user."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/settings_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("watch", + Some(r##"Watch for changes to Settings resources."##), + "Details at http://byron.github.io/google-apis-rs/google_calendar3_cli/settings_watch", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("calendar3") + .author("Sebastian Thiel ") + .version("0.2.0+20150326") + .about("Lets you manipulate events and other calendar data.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_calendar3_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/calendar3/Cargo.toml b/gen/calendar3/Cargo.toml index e8eab7f2e7..71c7bcc421 100644 --- a/gen/calendar3/Cargo.toml +++ b/gen/calendar3/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-calendar3" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel "] description = "A complete library to interact with calendar (protocol v3)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/calendar3" @@ -15,9 +15,10 @@ keywords = ["calendar", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/calendar3/README.md b/gen/calendar3/README.md index 00075fd0b6..5b3c73f33f 100644 --- a/gen/calendar3/README.md +++ b/gen/calendar3/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-calendar3` library allows access to all features of the *Google calendar* service. -This documentation was generated from *calendar* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *calendar:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *calendar* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *calendar:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *calendar* *v3* API can be found at the [official documentation site](https://developers.google.com/google-apps/calendar/firstapp). @@ -216,7 +216,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_calendar3/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_calendar3/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/calendar3/src/cmn.rs b/gen/calendar3/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/calendar3/src/cmn.rs +++ b/gen/calendar3/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/calendar3/src/lib.rs b/gen/calendar3/src/lib.rs index 98efc85d5c..baa742d260 100644 --- a/gen/calendar3/src/lib.rs +++ b/gen/calendar3/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *calendar* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *calendar:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *calendar* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *calendar:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *calendar* *v3* API can be found at the //! [official documentation site](https://developers.google.com/google-apps/calendar/firstapp). @@ -217,7 +217,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -226,7 +226,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -242,6 +241,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -385,7 +385,7 @@ impl<'a, C, A> CalendarHub CalendarHub { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -415,7 +415,7 @@ impl<'a, C, A> CalendarHub } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -2479,6 +2479,7 @@ impl<'a, C, A> FreebusyQueryCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, FreeBusyResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2509,11 +2510,20 @@ impl<'a, C, A> FreebusyQueryCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2536,7 +2546,7 @@ impl<'a, C, A> FreebusyQueryCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2744,7 +2754,7 @@ impl<'a, C, A> SettingListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2766,7 +2776,7 @@ impl<'a, C, A> SettingListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2954,6 +2964,7 @@ impl<'a, C, A> SettingWatchCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Channel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2993,11 +3004,20 @@ impl<'a, C, A> SettingWatchCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3020,7 +3040,7 @@ impl<'a, C, A> SettingWatchCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3263,7 +3283,7 @@ impl<'a, C, A> SettingGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3285,7 +3305,7 @@ impl<'a, C, A> SettingGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3456,6 +3476,7 @@ impl<'a, C, A> CalendarListUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, CalendarListEntry)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3514,11 +3535,20 @@ impl<'a, C, A> CalendarListUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3541,7 +3571,7 @@ impl<'a, C, A> CalendarListUpdateCall<'a, C, A> where C: BorrowMut CalendarListDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3798,7 +3828,7 @@ impl<'a, C, A> CalendarListDeleteCall<'a, C, A> where C: BorrowMut CalendarListGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4027,7 +4057,7 @@ impl<'a, C, A> CalendarListGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4248,7 +4278,7 @@ impl<'a, C, A> CalendarListListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4270,7 +4300,7 @@ impl<'a, C, A> CalendarListListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4476,6 +4506,7 @@ impl<'a, C, A> CalendarListInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, CalendarListEntry)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4509,11 +4540,20 @@ impl<'a, C, A> CalendarListInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4536,7 +4576,7 @@ impl<'a, C, A> CalendarListInsertCall<'a, C, A> where C: BorrowMut CalendarListPatchCall<'a, C, A> where C: BorrowMut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CalendarListEntry)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4774,11 +4815,20 @@ impl<'a, C, A> CalendarListPatchCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4801,7 +4851,7 @@ impl<'a, C, A> CalendarListPatchCall<'a, C, A> where C: BorrowMut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5000,6 +5050,7 @@ impl<'a, C, A> CalendarListWatchCall<'a, C, A> where C: BorrowMut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Channel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5048,11 +5099,20 @@ impl<'a, C, A> CalendarListWatchCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5075,7 +5135,7 @@ impl<'a, C, A> CalendarListWatchCall<'a, C, A> where C: BorrowMut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5292,6 +5352,7 @@ impl<'a, C, A> CalendarPatchCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Calendar)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5347,11 +5408,20 @@ impl<'a, C, A> CalendarPatchCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5374,7 +5444,7 @@ impl<'a, C, A> CalendarPatchCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5602,7 +5672,7 @@ impl<'a, C, A> CalendarDeleteCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5624,7 +5694,7 @@ impl<'a, C, A> CalendarDeleteCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5831,7 +5901,7 @@ impl<'a, C, A> CalendarGetCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5853,7 +5923,7 @@ impl<'a, C, A> CalendarGetCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6069,7 +6139,7 @@ impl<'a, C, A> CalendarClearCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6091,7 +6161,7 @@ impl<'a, C, A> CalendarClearCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6249,6 +6319,7 @@ impl<'a, C, A> CalendarInsertCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Calendar)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6279,11 +6350,20 @@ impl<'a, C, A> CalendarInsertCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6306,7 +6386,7 @@ impl<'a, C, A> CalendarInsertCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6477,6 +6557,7 @@ impl<'a, C, A> CalendarUpdateCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Calendar)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6532,11 +6613,20 @@ impl<'a, C, A> CalendarUpdateCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6559,7 +6649,7 @@ impl<'a, C, A> CalendarUpdateCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6748,6 +6838,7 @@ impl<'a, C, A> AclWatchCall<'a, C, A> where C: BorrowMut, A: oaut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Channel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6815,11 +6906,20 @@ impl<'a, C, A> AclWatchCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6842,7 +6942,7 @@ impl<'a, C, A> AclWatchCall<'a, C, A> where C: BorrowMut, A: oaut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7054,6 +7154,7 @@ impl<'a, C, A> AclInsertCall<'a, C, A> where C: BorrowMut, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AclRule)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7109,11 +7210,20 @@ impl<'a, C, A> AclInsertCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7136,7 +7246,7 @@ impl<'a, C, A> AclInsertCall<'a, C, A> where C: BorrowMut, A: oau request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7318,6 +7428,7 @@ impl<'a, C, A> AclUpdateCall<'a, C, A> where C: BorrowMut, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AclRule)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7374,11 +7485,20 @@ impl<'a, C, A> AclUpdateCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7401,7 +7521,7 @@ impl<'a, C, A> AclUpdateCall<'a, C, A> where C: BorrowMut, A: oau request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7593,6 +7713,7 @@ impl<'a, C, A> AclPatchCall<'a, C, A> where C: BorrowMut, A: oaut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AclRule)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7649,11 +7770,20 @@ impl<'a, C, A> AclPatchCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7676,7 +7806,7 @@ impl<'a, C, A> AclPatchCall<'a, C, A> where C: BorrowMut, A: oaut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7935,7 +8065,7 @@ impl<'a, C, A> AclListCall<'a, C, A> where C: BorrowMut, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7957,7 +8087,7 @@ impl<'a, C, A> AclListCall<'a, C, A> where C: BorrowMut, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8206,7 +8336,7 @@ impl<'a, C, A> AclDeleteCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8228,7 +8358,7 @@ impl<'a, C, A> AclDeleteCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8447,7 +8577,7 @@ impl<'a, C, A> AclGetCall<'a, C, A> where C: BorrowMut, A: oauth2 if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8469,7 +8599,7 @@ impl<'a, C, A> AclGetCall<'a, C, A> where C: BorrowMut, A: oauth2 access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8647,6 +8777,7 @@ impl<'a, C, A> ChannelStopCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8676,11 +8807,20 @@ impl<'a, C, A> ChannelStopCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8703,7 +8843,7 @@ impl<'a, C, A> ChannelStopCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8886,7 +9026,7 @@ impl<'a, C, A> ColorGetCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8908,7 +9048,7 @@ impl<'a, C, A> ColorGetCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9121,7 +9261,7 @@ impl<'a, C, A> EventDeleteCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9143,7 +9283,7 @@ impl<'a, C, A> EventDeleteCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9323,6 +9463,7 @@ impl<'a, C, A> EventInsertCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Event)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9384,11 +9525,20 @@ impl<'a, C, A> EventInsertCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9411,7 +9561,7 @@ impl<'a, C, A> EventInsertCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9606,6 +9756,7 @@ impl<'a, C, A> EventImportCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Event)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9661,11 +9812,20 @@ impl<'a, C, A> EventImportCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9688,7 +9848,7 @@ impl<'a, C, A> EventImportCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9964,7 +10124,7 @@ impl<'a, C, A> EventInstanceCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9986,7 +10146,7 @@ impl<'a, C, A> EventInstanceCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10293,7 +10453,7 @@ impl<'a, C, A> EventGetCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10315,7 +10475,7 @@ impl<'a, C, A> EventGetCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10656,7 +10816,7 @@ impl<'a, C, A> EventListCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10678,7 +10838,7 @@ impl<'a, C, A> EventListCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10988,6 +11148,7 @@ impl<'a, C, A> EventPatchCall<'a, C, A> where C: BorrowMut, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Event)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11053,11 +11214,20 @@ impl<'a, C, A> EventPatchCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11080,7 +11250,7 @@ impl<'a, C, A> EventPatchCall<'a, C, A> where C: BorrowMut, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11349,7 +11519,7 @@ impl<'a, C, A> EventMoveCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11371,7 +11541,7 @@ impl<'a, C, A> EventMoveCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11574,6 +11744,7 @@ impl<'a, C, A> EventUpdateCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Event)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11639,11 +11810,20 @@ impl<'a, C, A> EventUpdateCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11666,7 +11846,7 @@ impl<'a, C, A> EventUpdateCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11912,6 +12092,7 @@ impl<'a, C, A> EventWatchCall<'a, C, A> where C: BorrowMut, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Channel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12026,11 +12207,20 @@ impl<'a, C, A> EventWatchCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12053,7 +12243,7 @@ impl<'a, C, A> EventWatchCall<'a, C, A> where C: BorrowMut, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -12423,7 +12613,7 @@ impl<'a, C, A> EventQuickAddCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12445,7 +12635,7 @@ impl<'a, C, A> EventQuickAddCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/civicinfo2-cli/Cargo.toml b/gen/civicinfo2-cli/Cargo.toml index a58cd078d5..be962d4eb3 100644 --- a/gen/civicinfo2-cli/Cargo.toml +++ b/gen/civicinfo2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-civicinfo2-cli" -version = "0.1.0+20150302" +version = "0.2.0+20150302" authors = ["Sebastian Thiel "] description = "A complete library to interact with Civic Info (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/civicinfo2-cli" @@ -17,15 +17,14 @@ keywords = ["civicinfo", "google", "cli"] name = "civicinfo2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-civicinfo2] path = "../civicinfo2" diff --git a/gen/civicinfo2-cli/README.md b/gen/civicinfo2-cli/README.md index 94eb08182d..67ee9910fb 100644 --- a/gen/civicinfo2-cli/README.md +++ b/gen/civicinfo2-cli/README.md @@ -10,21 +10,25 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *Civic Info* API can be found at the +[official documentation site](https://developers.google.com/civic-information). + # Usage -This documentation was generated from the *Civic Info* API at revision *20150302*. The CLI is at version *0.1.0*. +This documentation was generated from the *Civic Info* API at revision *20150302*. The CLI is at version *0.2.0*. ```bash - civicinfo2 [options] divisions search [-p ...] [-o ] - civicinfo2 [options] elections election-query [-p ...] [-o ] - civicinfo2 [options] elections voter-info-query
[-p ...] [-o ] - civicinfo2 [options] representatives representative-info-by-address [-p ...] [-o ] - civicinfo2 [options] representatives representative-info-by-division [-p ...] [-o ] +civicinfo2 [options] + divisions + search [-p ]... [-o ] + elections + election-query [-p ]... [-o ] + voter-info-query
[-p ]... [-o ] + representatives + representative-info-by-address [-p ]... [-o ] + representative-info-by-division [-p ]... [-o ] civicinfo2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_civicinfo2_cli/index.html - Configuration: --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/civicinfo2-cli/mkdocs.yml b/gen/civicinfo2-cli/mkdocs.yml index c8a6f6003c..660f2d0d34 100644 --- a/gen/civicinfo2-cli/mkdocs.yml +++ b/gen/civicinfo2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Civic Info v0.1.0+20150302 +site_name: Civic Info v0.2.0+20150302 site_url: http://byron.github.io/google-apis-rs/google-civicinfo2-cli site_description: Write integrating applications with bcore diff --git a/gen/civicinfo2-cli/src/cmn.rs b/gen/civicinfo2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/civicinfo2-cli/src/cmn.rs +++ b/gen/civicinfo2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/civicinfo2-cli/src/main.rs b/gen/civicinfo2-cli/src/main.rs index 1f1e48cca5..33d7be5a76 100644 --- a/gen/civicinfo2-cli/src/main.rs +++ b/gen/civicinfo2-cli/src/main.rs @@ -2,156 +2,150 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_civicinfo2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - civicinfo2 [options] divisions search [-p ...] [-o ] - civicinfo2 [options] elections election-query [-p ...] [-o ] - civicinfo2 [options] elections voter-info-query
[-p ...] [-o ] - civicinfo2 [options] representatives representative-info-by-address [-p ...] [-o ] - civicinfo2 [options] representatives representative-info-by-division [-p ...] [-o ] - civicinfo2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_civicinfo2_cli/index.html - -Configuration: - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::CivicInfo>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _divisions_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { +impl<'n, 'a> Engine<'n, 'a> { + fn _divisions_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.divisions().search(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "query" => { call = call.query(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["query"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _elections_election_query(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _elections_election_query(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.elections().election_query(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _elections_voter_info_query(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.elections().voter_info_query(&self.opt.arg_address); - for parg in self.opt.arg_v.iter() { + fn _elections_voter_info_query(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.elections().voter_info_query(opt.value_of("address").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "official-only" => { @@ -160,47 +154,51 @@ impl Engine { "election-id" => { call = call.election_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["election-id", "official-only"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _representatives_representative_info_by_address(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _representatives_representative_info_by_address(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.representatives().representative_info_by_address(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "roles" => { @@ -215,47 +213,51 @@ impl Engine { "address" => { call = call.address(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["include-offices", "levels", "roles", "address"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _representatives_representative_info_by_division(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.representatives().representative_info_by_division(&self.opt.arg_ocd_id); - for parg in self.opt.arg_v.iter() { + fn _representatives_representative_info_by_division(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.representatives().representative_info_by_division(opt.value_of("ocd-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "roles" => { @@ -267,88 +269,111 @@ impl Engine { "levels" => { call = call.add_levels(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["levels", "recursive", "roles"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_divisions { - if self.opt.cmd_search { - call_result = self._divisions_search(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("divisions", Some(opt)) => { + match opt.subcommand() { + ("search", Some(opt)) => { + call_result = self._divisions_search(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("divisions".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("elections", Some(opt)) => { + match opt.subcommand() { + ("election-query", Some(opt)) => { + call_result = self._elections_election_query(opt, dry_run, &mut err); + }, + ("voter-info-query", Some(opt)) => { + call_result = self._elections_voter_info_query(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("elections".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("representatives", Some(opt)) => { + match opt.subcommand() { + ("representative-info-by-address", Some(opt)) => { + call_result = self._representatives_representative_info_by_address(opt, dry_run, &mut err); + }, + ("representative-info-by-division", Some(opt)) => { + call_result = self._representatives_representative_info_by_division(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("representatives".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_elections { - if self.opt.cmd_election_query { - call_result = self._elections_election_query(dry_run, &mut err); - } else if self.opt.cmd_voter_info_query { - call_result = self._elections_voter_info_query(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_representatives { - if self.opt.cmd_representative_info_by_address { - call_result = self._representatives_representative_info_by_address(dry_run, &mut err); - } else if self.opt.cmd_representative_info_by_division { - call_result = self._representatives_representative_info_by_division(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -361,7 +386,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -374,7 +399,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -384,37 +409,219 @@ impl Engine { let engine = Engine { opt: opt, hub: api::CivicInfo::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("divisions", "methods: 'search'", vec![ + ("search", + Some(r##"Searches for political divisions by their natural name or OCD ID."##), + "Details at http://byron.github.io/google-apis-rs/google_civicinfo2_cli/divisions_search", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("elections", "methods: 'election-query' and 'voter-info-query'", vec![ + ("election-query", + Some(r##"List of available elections to query."##), + "Details at http://byron.github.io/google-apis-rs/google_civicinfo2_cli/elections_election-query", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("voter-info-query", + Some(r##"Looks up information relevant to a voter based on the voter's registered address."##), + "Details at http://byron.github.io/google-apis-rs/google_civicinfo2_cli/elections_voter-info-query", + vec![ + (Some(r##"address"##), + None, + Some(r##"The registered address of the voter to look up."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("representatives", "methods: 'representative-info-by-address' and 'representative-info-by-division'", vec![ + ("representative-info-by-address", + Some(r##"Looks up political geography and representative information for a single address."##), + "Details at http://byron.github.io/google-apis-rs/google_civicinfo2_cli/representatives_representative-info-by-address", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("representative-info-by-division", + Some(r##"Looks up representative information for a single geographic division."##), + "Details at http://byron.github.io/google-apis-rs/google_civicinfo2_cli/representatives_representative-info-by-division", + vec![ + (Some(r##"ocd-id"##), + None, + Some(r##"The Open Civic Data division identifier of the division to look up."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("civicinfo2") + .author("Sebastian Thiel ") + .version("0.2.0+20150302") + .about("An API for accessing civic information.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_civicinfo2_cli") + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/civicinfo2/Cargo.toml b/gen/civicinfo2/Cargo.toml index 071dc47367..79cbe9ce17 100644 --- a/gen/civicinfo2/Cargo.toml +++ b/gen/civicinfo2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-civicinfo2" -version = "0.1.6+20150302" +version = "0.1.7+20150302" authors = ["Sebastian Thiel "] description = "A complete library to interact with Civic Info (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/civicinfo2" @@ -15,9 +15,10 @@ keywords = ["civicinfo", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/civicinfo2/README.md b/gen/civicinfo2/README.md index 7c9c6b9c22..34077c5e28 100644 --- a/gen/civicinfo2/README.md +++ b/gen/civicinfo2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-civicinfo2` library allows access to all features of the *Google Civic Info* service. -This documentation was generated from *Civic Info* crate version *0.1.6+20150302*, where *20150302* is the exact revision of the *civicinfo:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *Civic Info* crate version *0.1.7+20150302*, where *20150302* is the exact revision of the *civicinfo:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *Civic Info* *v2* API can be found at the [official documentation site](https://developers.google.com/civic-information). @@ -164,7 +164,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_civicinfo2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_civicinfo2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/civicinfo2/src/cmn.rs b/gen/civicinfo2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/civicinfo2/src/cmn.rs +++ b/gen/civicinfo2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/civicinfo2/src/lib.rs b/gen/civicinfo2/src/lib.rs index 804f05d9d7..ddaff5ca7f 100644 --- a/gen/civicinfo2/src/lib.rs +++ b/gen/civicinfo2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *Civic Info* crate version *0.1.6+20150302*, where *20150302* is the exact revision of the *civicinfo:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *Civic Info* crate version *0.1.7+20150302*, where *20150302* is the exact revision of the *civicinfo:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *Civic Info* *v2* API can be found at the //! [official documentation site](https://developers.google.com/civic-information). @@ -165,7 +165,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -174,7 +174,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -190,6 +189,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -286,7 +286,7 @@ impl<'a, C, A> CivicInfo CivicInfo { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -301,7 +301,7 @@ impl<'a, C, A> CivicInfo } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1147,7 +1147,7 @@ impl<'a, C, A> DivisionSearchCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1155,7 +1155,7 @@ impl<'a, C, A> DivisionSearchCall<'a, C, A> where C: BorrowMut, A loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -1334,7 +1334,7 @@ impl<'a, C, A> ElectionElectionQueryCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1342,7 +1342,7 @@ impl<'a, C, A> ElectionElectionQueryCall<'a, C, A> where C: BorrowMut ElectionVoterInfoQueryCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1534,7 +1534,7 @@ impl<'a, C, A> ElectionVoterInfoQueryCall<'a, C, A> where C: BorrowMut RepresentativeRepresentativeInfoByAddresCall<'a, C, A> where C: B if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1766,7 +1766,7 @@ impl<'a, C, A> RepresentativeRepresentativeInfoByAddresCall<'a, C, A> where C: B loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -2017,7 +2017,7 @@ impl<'a, C, A> RepresentativeRepresentativeInfoByDivisionCall<'a, C, A> where C: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2025,7 +2025,7 @@ impl<'a, C, A> RepresentativeRepresentativeInfoByDivisionCall<'a, C, A> where C: loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); diff --git a/gen/cloudlatencytest2-cli/Cargo.toml b/gen/cloudlatencytest2-cli/Cargo.toml index 24d404a9a4..f5eb90ab94 100644 --- a/gen/cloudlatencytest2-cli/Cargo.toml +++ b/gen/cloudlatencytest2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-cloudlatencytest2-cli" -version = "0.1.0+20150206" +version = "0.2.0+20150206" authors = ["Sebastian Thiel "] description = "A complete library to interact with cloudlatencytest (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/cloudlatencytest2-cli" @@ -16,15 +16,14 @@ keywords = ["cloudlatencytest", "google", "cli"] name = "cloudlatencytest2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-cloudlatencytest2] path = "../cloudlatencytest2" diff --git a/gen/cloudlatencytest2-cli/README.md b/gen/cloudlatencytest2-cli/README.md index b38a2bfd70..c3e0acbe79 100644 --- a/gen/cloudlatencytest2-cli/README.md +++ b/gen/cloudlatencytest2-cli/README.md @@ -12,20 +12,19 @@ If data-structures are requested, these will be returned as pretty-printed JSON, # Usage -This documentation was generated from the *cloudlatencytest* API at revision *20150206*. The CLI is at version *0.1.0*. +This documentation was generated from the *cloudlatencytest* API at revision *20150206*. The CLI is at version *0.2.0*. ```bash - cloudlatencytest2 [options] statscollection updateaggregatedstats -r ... [-p ...] [-o ] - cloudlatencytest2 [options] statscollection updatestats -r ... [-p ...] [-o ] +cloudlatencytest2 [options] + statscollection + updateaggregatedstats (-r )... [-p ]... [-o ] + updatestats (-r )... [-p ]... [-o ] cloudlatencytest2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_cloudlatencytest2_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/cloudlatencytest2-cli/mkdocs.yml b/gen/cloudlatencytest2-cli/mkdocs.yml index 4337528929..1a6ab211bb 100644 --- a/gen/cloudlatencytest2-cli/mkdocs.yml +++ b/gen/cloudlatencytest2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: cloudlatencytest v0.1.0+20150206 +site_name: cloudlatencytest v0.2.0+20150206 site_url: http://byron.github.io/google-apis-rs/google-cloudlatencytest2-cli site_description: Write integrating applications with bcore diff --git a/gen/cloudlatencytest2-cli/src/cmn.rs b/gen/cloudlatencytest2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/cloudlatencytest2-cli/src/cmn.rs +++ b/gen/cloudlatencytest2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/cloudlatencytest2-cli/src/main.rs b/gen/cloudlatencytest2-cli/src/main.rs index 69cd091dbb..46517e2958 100644 --- a/gen/cloudlatencytest2-cli/src/main.rs +++ b/gen/cloudlatencytest2-cli/src/main.rs @@ -2,70 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_cloudlatencytest2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - cloudlatencytest2 [options] statscollection updateaggregatedstats -r ... [-p ...] [-o ] - cloudlatencytest2 [options] statscollection updatestats -r ... [-p ...] [-o ] - cloudlatencytest2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_cloudlatencytest2_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Cloudlatencytest>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _statscollection_updateaggregatedstats(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { +impl<'n, 'a> Engine<'n, 'a> { + fn _statscollection_updateaggregatedstats(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AggregatedStats::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -81,60 +66,65 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.statscollection().updateaggregatedstats(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _statscollection_updatestats(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _statscollection_updatestats(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Stats::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -153,83 +143,98 @@ impl Engine { request.time = Some(arg_from_str(value.unwrap_or("0.0"), err, "time", "number")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["time"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.statscollection().updatestats(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_statscollection { - if self.opt.cmd_updateaggregatedstats { - call_result = self._statscollection_updateaggregatedstats(dry_run, &mut err); - } else if self.opt.cmd_updatestats { - call_result = self._statscollection_updatestats(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("statscollection", Some(opt)) => { + match opt.subcommand() { + ("updateaggregatedstats", Some(opt)) => { + call_result = self._statscollection_updateaggregatedstats(opt, dry_run, &mut err); + }, + ("updatestats", Some(opt)) => { + call_result = self._statscollection_updatestats(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("statscollection".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -242,7 +247,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -255,7 +260,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -265,37 +270,170 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Cloudlatencytest::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("statscollection", "methods: 'updateaggregatedstats' and 'updatestats'", vec![ + ("updateaggregatedstats", + Some(r##"RPC to update the new TCP stats."##), + "Details at http://byron.github.io/google-apis-rs/google_cloudlatencytest2_cli/statscollection_updateaggregatedstats", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("updatestats", + Some(r##"RPC to update the new TCP stats."##), + "Details at http://byron.github.io/google-apis-rs/google_cloudlatencytest2_cli/statscollection_updatestats", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("cloudlatencytest2") + .author("Sebastian Thiel ") + .version("0.2.0+20150206") + .about("A Test API to report latency data.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_cloudlatencytest2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/cloudlatencytest2/Cargo.toml b/gen/cloudlatencytest2/Cargo.toml index 8f8eb3ea1d..f5e71722d6 100644 --- a/gen/cloudlatencytest2/Cargo.toml +++ b/gen/cloudlatencytest2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-cloudlatencytest2" -version = "0.1.6+20150206" +version = "0.1.7+20150206" authors = ["Sebastian Thiel "] description = "A complete library to interact with cloudlatencytest (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/cloudlatencytest2" @@ -14,9 +14,10 @@ keywords = ["cloudlatencytest", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/cloudlatencytest2/README.md b/gen/cloudlatencytest2/README.md index 2e4e50fd37..5fe9cee8f5 100644 --- a/gen/cloudlatencytest2/README.md +++ b/gen/cloudlatencytest2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-cloudlatencytest2` library allows access to all features of the *Google cloudlatencytest* service. -This documentation was generated from *cloudlatencytest* crate version *0.1.6+20150206*, where *20150206* is the exact revision of the *cloudlatencytest:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *cloudlatencytest* crate version *0.1.7+20150206*, where *20150206* is the exact revision of the *cloudlatencytest:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. # Features Handle the following *Resources* with ease from the central [hub](http://byron.github.io/google-apis-rs/google_cloudlatencytest2/struct.Cloudlatencytest.html) ... @@ -160,7 +160,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_cloudlatencytest2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_cloudlatencytest2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/cloudlatencytest2/src/cmn.rs b/gen/cloudlatencytest2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/cloudlatencytest2/src/cmn.rs +++ b/gen/cloudlatencytest2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/cloudlatencytest2/src/lib.rs b/gen/cloudlatencytest2/src/lib.rs index 59048d6ebb..1fb1f82fcb 100644 --- a/gen/cloudlatencytest2/src/lib.rs +++ b/gen/cloudlatencytest2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *cloudlatencytest* crate version *0.1.6+20150206*, where *20150206* is the exact revision of the *cloudlatencytest:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *cloudlatencytest* crate version *0.1.7+20150206*, where *20150206* is the exact revision of the *cloudlatencytest:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! The original source code is [on github](https://github.com/Byron/google-apis-rs/tree/master/gen/cloudlatencytest2). //! # Features //! @@ -161,7 +161,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -170,7 +170,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -186,6 +185,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -308,7 +308,7 @@ impl<'a, C, A> Cloudlatencytest Cloudlatencytest { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -317,7 +317,7 @@ impl<'a, C, A> Cloudlatencytest } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -598,6 +598,7 @@ impl<'a, C, A> StatscollectionUpdateaggregatedstatCall<'a, C, A> where C: Borrow /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AggregatedStatsReply)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -628,11 +629,20 @@ impl<'a, C, A> StatscollectionUpdateaggregatedstatCall<'a, C, A> where C: Borrow if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -655,7 +665,7 @@ impl<'a, C, A> StatscollectionUpdateaggregatedstatCall<'a, C, A> where C: Borrow request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -825,6 +835,7 @@ impl<'a, C, A> StatscollectionUpdatestatCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, StatsReply)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -855,11 +866,20 @@ impl<'a, C, A> StatscollectionUpdatestatCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -882,7 +902,7 @@ impl<'a, C, A> StatscollectionUpdatestatCall<'a, C, A> where C: BorrowMut"] description = "A complete library to interact with Cloud Monitoring (protocol v2beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/cloudmonitoring2_beta2-cli" @@ -17,15 +17,14 @@ keywords = ["cloudmonitoring", "google", "cli"] name = "cloudmonitoring2-beta2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-cloudmonitoring2_beta2] path = "../cloudmonitoring2_beta2" diff --git a/gen/cloudmonitoring2_beta2-cli/README.md b/gen/cloudmonitoring2_beta2-cli/README.md index f7cb8b2377..beed3c8b2d 100644 --- a/gen/cloudmonitoring2_beta2-cli/README.md +++ b/gen/cloudmonitoring2_beta2-cli/README.md @@ -10,26 +10,30 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *Cloud Monitoring* API can be found at the +[official documentation site](https://cloud.google.com/monitoring/v2beta2/). + # Usage -This documentation was generated from the *Cloud Monitoring* API at revision *20150401*. The CLI is at version *0.1.0*. +This documentation was generated from the *Cloud Monitoring* API at revision *20150401*. The CLI is at version *0.2.0*. ```bash - cloudmonitoring2-beta2 [options] metric-descriptors create -r ... [-p ...] [-o ] - cloudmonitoring2-beta2 [options] metric-descriptors delete [-p ...] [-o ] - cloudmonitoring2-beta2 [options] metric-descriptors list -r ... [-p ...] [-o ] - cloudmonitoring2-beta2 [options] timeseries list -r ... [-p ...] [-o ] - cloudmonitoring2-beta2 [options] timeseries write -r ... [-p ...] [-o ] - cloudmonitoring2-beta2 [options] timeseries-descriptors list -r ... [-p ...] [-o ] +cloudmonitoring2-beta2 [options] + metric-descriptors + create (-r )... [-p ]... [-o ] + delete [-p ]... [-o ] + list (-r )... [-p ]... [-o ] + timeseries + list (-r )... [-p ]... [-o ] + write (-r )... [-p ]... [-o ] + timeseries-descriptors + list (-r )... [-p ]... [-o ] cloudmonitoring2-beta2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_cloudmonitoring2_beta2_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/cloudmonitoring2_beta2-cli/mkdocs.yml b/gen/cloudmonitoring2_beta2-cli/mkdocs.yml index e7500b963c..118588fb88 100644 --- a/gen/cloudmonitoring2_beta2-cli/mkdocs.yml +++ b/gen/cloudmonitoring2_beta2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Cloud Monitoring v0.1.0+20150401 +site_name: Cloud Monitoring v0.2.0+20150401 site_url: http://byron.github.io/google-apis-rs/google-cloudmonitoring2_beta2-cli site_description: Write integrating applications with bcore diff --git a/gen/cloudmonitoring2_beta2-cli/src/cmn.rs b/gen/cloudmonitoring2_beta2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/cloudmonitoring2_beta2-cli/src/cmn.rs +++ b/gen/cloudmonitoring2_beta2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/cloudmonitoring2_beta2-cli/src/main.rs b/gen/cloudmonitoring2_beta2-cli/src/main.rs index e0af43e97a..c1f851e8e1 100644 --- a/gen/cloudmonitoring2_beta2-cli/src/main.rs +++ b/gen/cloudmonitoring2_beta2-cli/src/main.rs @@ -2,74 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_cloudmonitoring2_beta2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - cloudmonitoring2-beta2 [options] metric-descriptors create -r ... [-p ...] [-o ] - cloudmonitoring2-beta2 [options] metric-descriptors delete [-p ...] [-o ] - cloudmonitoring2-beta2 [options] metric-descriptors list -r ... [-p ...] [-o ] - cloudmonitoring2-beta2 [options] timeseries list -r ... [-p ...] [-o ] - cloudmonitoring2-beta2 [options] timeseries write -r ... [-p ...] [-o ] - cloudmonitoring2-beta2 [options] timeseries-descriptors list -r ... [-p ...] [-o ] - cloudmonitoring2-beta2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_cloudmonitoring2_beta2_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::CloudMonitoring>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _metric_descriptors_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { +impl<'n, 'a> Engine<'n, 'a> { + fn _metric_descriptors_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::MetricDescriptor::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -110,106 +91,115 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["description", "metric-type", "name", "project", "type-descriptor", "value-type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.metric_descriptors().create(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.metric_descriptors().create(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _metric_descriptors_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.metric_descriptors().delete(&self.opt.arg_project, &self.opt.arg_metric); - for parg in self.opt.arg_v.iter() { + fn _metric_descriptors_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.metric_descriptors().delete(opt.value_of("project").unwrap_or(""), opt.value_of("metric").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _metric_descriptors_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _metric_descriptors_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ListMetricDescriptorsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -228,12 +218,13 @@ impl Engine { request.kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.metric_descriptors().list(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.metric_descriptors().list(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "query" => { @@ -245,52 +236,56 @@ impl Engine { "count" => { call = call.count(arg_from_str(value.unwrap_or("-0"), err, "count", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["count", "query", "page-token"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _timeseries_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _timeseries_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ListTimeseriesRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -309,12 +304,13 @@ impl Engine { request.kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.timeseries().list(request, &self.opt.arg_project, &self.opt.arg_metric, &self.opt.arg_youngest); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.timeseries().list(request, opt.value_of("project").unwrap_or(""), opt.value_of("metric").unwrap_or(""), opt.value_of("youngest").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "window" => { @@ -338,52 +334,56 @@ impl Engine { "aggregator" => { call = call.aggregator(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["count", "timespan", "aggregator", "labels", "page-token", "window", "oldest"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _timeseries_write(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _timeseries_write(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::WriteTimeseriesRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -406,60 +406,65 @@ impl Engine { request.common_labels.as_mut().unwrap().insert(key.to_string(), value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["common-labels"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.timeseries().write(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.timeseries().write(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _timeseries_descriptors_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _timeseries_descriptors_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ListTimeseriesDescriptorsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -478,12 +483,13 @@ impl Engine { request.kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.timeseries_descriptors().list(request, &self.opt.arg_project, &self.opt.arg_metric, &self.opt.arg_youngest); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.timeseries_descriptors().list(request, opt.value_of("project").unwrap_or(""), opt.value_of("metric").unwrap_or(""), opt.value_of("youngest").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "window" => { @@ -507,93 +513,117 @@ impl Engine { "aggregator" => { call = call.aggregator(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["count", "timespan", "aggregator", "labels", "page-token", "window", "oldest"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_metric_descriptors { - if self.opt.cmd_create { - call_result = self._metric_descriptors_create(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._metric_descriptors_delete(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._metric_descriptors_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("metric-descriptors", Some(opt)) => { + match opt.subcommand() { + ("create", Some(opt)) => { + call_result = self._metric_descriptors_create(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._metric_descriptors_delete(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._metric_descriptors_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("metric-descriptors".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("timeseries", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._timeseries_list(opt, dry_run, &mut err); + }, + ("write", Some(opt)) => { + call_result = self._timeseries_write(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("timeseries".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("timeseries-descriptors", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._timeseries_descriptors_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("timeseries-descriptors".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_timeseries { - if self.opt.cmd_list { - call_result = self._timeseries_list(dry_run, &mut err); - } else if self.opt.cmd_write { - call_result = self._timeseries_write(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_timeseries_descriptors { - if self.opt.cmd_list { - call_result = self._timeseries_descriptors_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -606,7 +636,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -619,7 +649,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -629,37 +659,324 @@ impl Engine { let engine = Engine { opt: opt, hub: api::CloudMonitoring::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("metric-descriptors", "methods: 'create', 'delete' and 'list'", vec![ + ("create", + Some(r##"Create a new metric."##), + "Details at http://byron.github.io/google-apis-rs/google_cloudmonitoring2_beta2_cli/metric-descriptors_create", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project id. The value can be the numeric project ID or string-based project name."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Delete an existing metric."##), + "Details at http://byron.github.io/google-apis-rs/google_cloudmonitoring2_beta2_cli/metric-descriptors_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project ID to which the metric belongs."##), + Some(true), + Some(false)), + + (Some(r##"metric"##), + None, + Some(r##"Name of the metric."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List metric descriptors that match the query. If the query is not set, then all of the metric descriptors will be returned. Large responses will be paginated, use the nextPageToken returned in the response to request subsequent pages of results by setting the pageToken query parameter to the value of the nextPageToken."##), + "Details at http://byron.github.io/google-apis-rs/google_cloudmonitoring2_beta2_cli/metric-descriptors_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project id. The value can be the numeric project ID or string-based project name."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("timeseries", "methods: 'list' and 'write'", vec![ + ("list", + Some(r##"List the data points of the time series that match the metric and labels values and that have data points in the interval. Large responses are paginated; use the nextPageToken returned in the response to request subsequent pages of results by setting the pageToken query parameter to the value of the nextPageToken."##), + "Details at http://byron.github.io/google-apis-rs/google_cloudmonitoring2_beta2_cli/timeseries_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project ID to which this time series belongs. The value can be the numeric project ID or string-based project name."##), + Some(true), + Some(false)), + + (Some(r##"metric"##), + None, + Some(r##"Metric names are protocol-free URLs as listed in the Supported Metrics page. For example, compute.googleapis.com/instance/disk/read_ops_count."##), + Some(true), + Some(false)), + + (Some(r##"youngest"##), + None, + Some(r##"End of the time interval (inclusive), which is expressed as an RFC 3339 timestamp."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("write", + Some(r##"Put data points to one or more time series for one or more metrics. If a time series does not exist, a new time series will be created. It is not allowed to write a time series point that is older than the existing youngest point of that time series. Points that are older than the existing youngest point of that time series will be discarded silently. Therefore, users should make sure that points of a time series are written sequentially in the order of their end time."##), + "Details at http://byron.github.io/google-apis-rs/google_cloudmonitoring2_beta2_cli/timeseries_write", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project ID. The value can be the numeric project ID or string-based project name."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("timeseries-descriptors", "methods: 'list'", vec![ + ("list", + Some(r##"List the descriptors of the time series that match the metric and labels values and that have data points in the interval. Large responses are paginated; use the nextPageToken returned in the response to request subsequent pages of results by setting the pageToken query parameter to the value of the nextPageToken."##), + "Details at http://byron.github.io/google-apis-rs/google_cloudmonitoring2_beta2_cli/timeseries-descriptors_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project ID to which this time series belongs. The value can be the numeric project ID or string-based project name."##), + Some(true), + Some(false)), + + (Some(r##"metric"##), + None, + Some(r##"Metric names are protocol-free URLs as listed in the Supported Metrics page. For example, compute.googleapis.com/instance/disk/read_ops_count."##), + Some(true), + Some(false)), + + (Some(r##"youngest"##), + None, + Some(r##"End of the time interval (inclusive), which is expressed as an RFC 3339 timestamp."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("cloudmonitoring2-beta2") + .author("Sebastian Thiel ") + .version("0.2.0+20150401") + .about("API for accessing Google Cloud and API monitoring data.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_cloudmonitoring2_beta2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/cloudmonitoring2_beta2/Cargo.toml b/gen/cloudmonitoring2_beta2/Cargo.toml index a5d9abdcba..4465c11b9b 100644 --- a/gen/cloudmonitoring2_beta2/Cargo.toml +++ b/gen/cloudmonitoring2_beta2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-cloudmonitoring2_beta2" -version = "0.1.6+20150401" +version = "0.1.7+20150401" authors = ["Sebastian Thiel "] description = "A complete library to interact with Cloud Monitoring (protocol v2beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/cloudmonitoring2_beta2" @@ -15,9 +15,10 @@ keywords = ["cloudmonitoring", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/cloudmonitoring2_beta2/README.md b/gen/cloudmonitoring2_beta2/README.md index 0257e29325..5def072a03 100644 --- a/gen/cloudmonitoring2_beta2/README.md +++ b/gen/cloudmonitoring2_beta2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-cloudmonitoring2_beta2` library allows access to all features of the *Google Cloud Monitoring* service. -This documentation was generated from *Cloud Monitoring* crate version *0.1.6+20150401*, where *20150401* is the exact revision of the *cloudmonitoring:v2beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *Cloud Monitoring* crate version *0.1.7+20150401*, where *20150401* is the exact revision of the *cloudmonitoring:v2beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *Cloud Monitoring* *v2_beta2* API can be found at the [official documentation site](https://cloud.google.com/monitoring/v2beta2/). @@ -172,7 +172,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_cloudmonitoring2_beta2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_cloudmonitoring2_beta2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/cloudmonitoring2_beta2/src/cmn.rs b/gen/cloudmonitoring2_beta2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/cloudmonitoring2_beta2/src/cmn.rs +++ b/gen/cloudmonitoring2_beta2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/cloudmonitoring2_beta2/src/lib.rs b/gen/cloudmonitoring2_beta2/src/lib.rs index 882f455501..1771f240b6 100644 --- a/gen/cloudmonitoring2_beta2/src/lib.rs +++ b/gen/cloudmonitoring2_beta2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *Cloud Monitoring* crate version *0.1.6+20150401*, where *20150401* is the exact revision of the *cloudmonitoring:v2beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *Cloud Monitoring* crate version *0.1.7+20150401*, where *20150401* is the exact revision of the *cloudmonitoring:v2beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *Cloud Monitoring* *v2_beta2* API can be found at the //! [official documentation site](https://cloud.google.com/monitoring/v2beta2/). @@ -173,7 +173,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -182,7 +182,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -198,6 +197,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -323,7 +323,7 @@ impl<'a, C, A> CloudMonitoring CloudMonitoring { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -338,7 +338,7 @@ impl<'a, C, A> CloudMonitoring } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1100,6 +1100,7 @@ impl<'a, C, A> TimeseriesDescriptorListCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, ListTimeseriesDescriptorsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1182,11 +1183,20 @@ impl<'a, C, A> TimeseriesDescriptorListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1209,7 +1219,7 @@ impl<'a, C, A> TimeseriesDescriptorListCall<'a, C, A> where C: BorrowMut TimeseryWriteCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, WriteTimeseriesResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1531,11 +1542,20 @@ impl<'a, C, A> TimeseryWriteCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1558,7 +1578,7 @@ impl<'a, C, A> TimeseryWriteCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1755,6 +1775,7 @@ impl<'a, C, A> TimeseryListCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ListTimeseriesResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1837,11 +1858,20 @@ impl<'a, C, A> TimeseryListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1864,7 +1894,7 @@ impl<'a, C, A> TimeseryListCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2137,6 +2167,7 @@ impl<'a, C, A> MetricDescriptorListCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, ListMetricDescriptorsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2201,11 +2232,20 @@ impl<'a, C, A> MetricDescriptorListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2228,7 +2268,7 @@ impl<'a, C, A> MetricDescriptorListCall<'a, C, A> where C: BorrowMut MetricDescriptorDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2502,7 +2542,7 @@ impl<'a, C, A> MetricDescriptorDeleteCall<'a, C, A> where C: BorrowMut MetricDescriptorCreateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, MetricDescriptor)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2736,11 +2777,20 @@ impl<'a, C, A> MetricDescriptorCreateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2763,7 +2813,7 @@ impl<'a, C, A> MetricDescriptorCreateCall<'a, C, A> where C: BorrowMut"] description = "A complete library to interact with compute (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/compute1-cli" @@ -17,15 +17,14 @@ keywords = ["compute", "google", "cli"] name = "compute1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-compute1] path = "../compute1" diff --git a/gen/compute1-cli/README.md b/gen/compute1-cli/README.md index bc8a65237d..6292add6f2 100644 --- a/gen/compute1-cli/README.md +++ b/gen/compute1-cli/README.md @@ -10,166 +10,196 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *compute* API can be found at the +[official documentation site](https://developers.google.com/compute/docs/reference/latest/). + # Usage -This documentation was generated from the *compute* API at revision *20150326*. The CLI is at version *0.1.0*. +This documentation was generated from the *compute* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - compute1 [options] addresses aggregated-list [-p ...] [-o ] - compute1 [options] addresses delete
[-p ...] [-o ] - compute1 [options] addresses get
[-p ...] [-o ] - compute1 [options] addresses insert -r ... [-p ...] [-o ] - compute1 [options] addresses list [-p ...] [-o ] - compute1 [options] backend-services delete [-p ...] [-o ] - compute1 [options] backend-services get [-p ...] [-o ] - compute1 [options] backend-services get-health -r ... [-p ...] [-o ] - compute1 [options] backend-services insert -r ... [-p ...] [-o ] - compute1 [options] backend-services list [-p ...] [-o ] - compute1 [options] backend-services patch -r ... [-p ...] [-o ] - compute1 [options] backend-services update -r ... [-p ...] [-o ] - compute1 [options] disk-types aggregated-list [-p ...] [-o ] - compute1 [options] disk-types get [-p ...] [-o ] - compute1 [options] disk-types list [-p ...] [-o ] - compute1 [options] disks aggregated-list [-p ...] [-o ] - compute1 [options] disks create-snapshot -r ... [-p ...] [-o ] - compute1 [options] disks delete [-p ...] [-o ] - compute1 [options] disks get [-p ...] [-o ] - compute1 [options] disks insert -r ... [-p ...] [-o ] - compute1 [options] disks list [-p ...] [-o ] - compute1 [options] firewalls delete [-p ...] [-o ] - compute1 [options] firewalls get [-p ...] [-o ] - compute1 [options] firewalls insert -r ... [-p ...] [-o ] - compute1 [options] firewalls list [-p ...] [-o ] - compute1 [options] firewalls patch -r ... [-p ...] [-o ] - compute1 [options] firewalls update -r ... [-p ...] [-o ] - compute1 [options] forwarding-rules aggregated-list [-p ...] [-o ] - compute1 [options] forwarding-rules delete [-p ...] [-o ] - compute1 [options] forwarding-rules get [-p ...] [-o ] - compute1 [options] forwarding-rules insert -r ... [-p ...] [-o ] - compute1 [options] forwarding-rules list [-p ...] [-o ] - compute1 [options] forwarding-rules set-target -r ... [-p ...] [-o ] - compute1 [options] global-addresses delete
[-p ...] [-o ] - compute1 [options] global-addresses get
[-p ...] [-o ] - compute1 [options] global-addresses insert -r ... [-p ...] [-o ] - compute1 [options] global-addresses list [-p ...] [-o ] - compute1 [options] global-forwarding-rules delete [-p ...] [-o ] - compute1 [options] global-forwarding-rules get [-p ...] [-o ] - compute1 [options] global-forwarding-rules insert -r ... [-p ...] [-o ] - compute1 [options] global-forwarding-rules list [-p ...] [-o ] - compute1 [options] global-forwarding-rules set-target -r ... [-p ...] [-o ] - compute1 [options] global-operations aggregated-list [-p ...] [-o ] - compute1 [options] global-operations delete [-p ...] - compute1 [options] global-operations get [-p ...] [-o ] - compute1 [options] global-operations list [-p ...] [-o ] - compute1 [options] http-health-checks delete [-p ...] [-o ] - compute1 [options] http-health-checks get [-p ...] [-o ] - compute1 [options] http-health-checks insert -r ... [-p ...] [-o ] - compute1 [options] http-health-checks list [-p ...] [-o ] - compute1 [options] http-health-checks patch -r ... [-p ...] [-o ] - compute1 [options] http-health-checks update -r ... [-p ...] [-o ] - compute1 [options] images delete [-p ...] [-o ] - compute1 [options] images deprecate -r ... [-p ...] [-o ] - compute1 [options] images get [-p ...] [-o ] - compute1 [options] images insert -r ... [-p ...] [-o ] - compute1 [options] images list [-p ...] [-o ] - compute1 [options] instance-templates delete [-p ...] [-o ] - compute1 [options] instance-templates get [-p ...] [-o ] - compute1 [options] instance-templates insert -r ... [-p ...] [-o ] - compute1 [options] instance-templates list [-p ...] [-o ] - compute1 [options] instances add-access-config -r ... [-p ...] [-o ] - compute1 [options] instances aggregated-list [-p ...] [-o ] - compute1 [options] instances attach-disk -r ... [-p ...] [-o ] - compute1 [options] instances delete [-p ...] [-o ] - compute1 [options] instances delete-access-config [-p ...] [-o ] - compute1 [options] instances detach-disk [-p ...] [-o ] - compute1 [options] instances get [-p ...] [-o ] - compute1 [options] instances get-serial-port-output [-p ...] [-o ] - compute1 [options] instances insert -r ... [-p ...] [-o ] - compute1 [options] instances list [-p ...] [-o ] - compute1 [options] instances reset [-p ...] [-o ] - compute1 [options] instances set-disk-auto-delete [-p ...] [-o ] - compute1 [options] instances set-metadata -r ... [-p ...] [-o ] - compute1 [options] instances set-scheduling -r ... [-p ...] [-o ] - compute1 [options] instances set-tags -r ... [-p ...] [-o ] - compute1 [options] instances start [-p ...] [-o ] - compute1 [options] instances stop [-p ...] [-o ] - compute1 [options] licenses get [-p ...] [-o ] - compute1 [options] machine-types aggregated-list [-p ...] [-o ] - compute1 [options] machine-types get [-p ...] [-o ] - compute1 [options] machine-types list [-p ...] [-o ] - compute1 [options] networks delete [-p ...] [-o ] - compute1 [options] networks get [-p ...] [-o ] - compute1 [options] networks insert -r ... [-p ...] [-o ] - compute1 [options] networks list [-p ...] [-o ] - compute1 [options] projects get [-p ...] [-o ] - compute1 [options] projects move-disk -r ... [-p ...] [-o ] - compute1 [options] projects move-instance -r ... [-p ...] [-o ] - compute1 [options] projects set-common-instance-metadata -r ... [-p ...] [-o ] - compute1 [options] projects set-usage-export-bucket -r ... [-p ...] [-o ] - compute1 [options] region-operations delete [-p ...] - compute1 [options] region-operations get [-p ...] [-o ] - compute1 [options] region-operations list [-p ...] [-o ] - compute1 [options] regions get [-p ...] [-o ] - compute1 [options] regions list [-p ...] [-o ] - compute1 [options] routes delete [-p ...] [-o ] - compute1 [options] routes get [-p ...] [-o ] - compute1 [options] routes insert -r ... [-p ...] [-o ] - compute1 [options] routes list [-p ...] [-o ] - compute1 [options] snapshots delete [-p ...] [-o ] - compute1 [options] snapshots get [-p ...] [-o ] - compute1 [options] snapshots list [-p ...] [-o ] - compute1 [options] target-http-proxies delete [-p ...] [-o ] - compute1 [options] target-http-proxies get [-p ...] [-o ] - compute1 [options] target-http-proxies insert -r ... [-p ...] [-o ] - compute1 [options] target-http-proxies list [-p ...] [-o ] - compute1 [options] target-http-proxies set-url-map -r ... [-p ...] [-o ] - compute1 [options] target-instances aggregated-list [-p ...] [-o ] - compute1 [options] target-instances delete [-p ...] [-o ] - compute1 [options] target-instances get [-p ...] [-o ] - compute1 [options] target-instances insert -r ... [-p ...] [-o ] - compute1 [options] target-instances list [-p ...] [-o ] - compute1 [options] target-pools add-health-check -r ... [-p ...] [-o ] - compute1 [options] target-pools add-instance -r ... [-p ...] [-o ] - compute1 [options] target-pools aggregated-list [-p ...] [-o ] - compute1 [options] target-pools delete [-p ...] [-o ] - compute1 [options] target-pools get [-p ...] [-o ] - compute1 [options] target-pools get-health -r ... [-p ...] [-o ] - compute1 [options] target-pools insert -r ... [-p ...] [-o ] - compute1 [options] target-pools list [-p ...] [-o ] - compute1 [options] target-pools remove-health-check -r ... [-p ...] [-o ] - compute1 [options] target-pools remove-instance -r ... [-p ...] [-o ] - compute1 [options] target-pools set-backup -r ... [-p ...] [-o ] - compute1 [options] target-vpn-gateways aggregated-list [-p ...] [-o ] - compute1 [options] target-vpn-gateways delete [-p ...] [-o ] - compute1 [options] target-vpn-gateways get [-p ...] [-o ] - compute1 [options] target-vpn-gateways insert -r ... [-p ...] [-o ] - compute1 [options] target-vpn-gateways list [-p ...] [-o ] - compute1 [options] url-maps delete [-p ...] [-o ] - compute1 [options] url-maps get [-p ...] [-o ] - compute1 [options] url-maps insert -r ... [-p ...] [-o ] - compute1 [options] url-maps list [-p ...] [-o ] - compute1 [options] url-maps patch -r ... [-p ...] [-o ] - compute1 [options] url-maps update -r ... [-p ...] [-o ] - compute1 [options] url-maps validate -r ... [-p ...] [-o ] - compute1 [options] vpn-tunnels aggregated-list [-p ...] [-o ] - compute1 [options] vpn-tunnels delete [-p ...] [-o ] - compute1 [options] vpn-tunnels get [-p ...] [-o ] - compute1 [options] vpn-tunnels insert -r ... [-p ...] [-o ] - compute1 [options] vpn-tunnels list [-p ...] [-o ] - compute1 [options] zone-operations delete [-p ...] - compute1 [options] zone-operations get [-p ...] [-o ] - compute1 [options] zone-operations list [-p ...] [-o ] - compute1 [options] zones get [-p ...] [-o ] - compute1 [options] zones list [-p ...] [-o ] +compute1 [options] + addresses + aggregated-list [-p ]... [-o ] + delete
[-p ]... [-o ] + get
[-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + backend-services + delete [-p ]... [-o ] + get [-p ]... [-o ] + get-health (-r )... [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + disk-types + aggregated-list [-p ]... [-o ] + get [-p ]... [-o ] + list [-p ]... [-o ] + disks + aggregated-list [-p ]... [-o ] + create-snapshot (-r )... [-p ]... [-o ] + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + firewalls + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + forwarding-rules + aggregated-list [-p ]... [-o ] + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + set-target (-r )... [-p ]... [-o ] + global-addresses + delete
[-p ]... [-o ] + get
[-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + global-forwarding-rules + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + set-target (-r )... [-p ]... [-o ] + global-operations + aggregated-list [-p ]... [-o ] + delete [-p ]... + get [-p ]... [-o ] + list [-p ]... [-o ] + http-health-checks + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + images + delete [-p ]... [-o ] + deprecate (-r )... [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + instance-templates + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + instances + add-access-config (-r )... [-p ]... [-o ] + aggregated-list [-p ]... [-o ] + attach-disk (-r )... [-p ]... [-o ] + delete [-p ]... [-o ] + delete-access-config [-p ]... [-o ] + detach-disk [-p ]... [-o ] + get [-p ]... [-o ] + get-serial-port-output [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + reset [-p ]... [-o ] + set-disk-auto-delete [-p ]... [-o ] + set-metadata (-r )... [-p ]... [-o ] + set-scheduling (-r )... [-p ]... [-o ] + set-tags (-r )... [-p ]... [-o ] + start [-p ]... [-o ] + stop [-p ]... [-o ] + licenses + get [-p ]... [-o ] + machine-types + aggregated-list [-p ]... [-o ] + get [-p ]... [-o ] + list [-p ]... [-o ] + networks + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + projects + get [-p ]... [-o ] + move-disk (-r )... [-p ]... [-o ] + move-instance (-r )... [-p ]... [-o ] + set-common-instance-metadata (-r )... [-p ]... [-o ] + set-usage-export-bucket (-r )... [-p ]... [-o ] + region-operations + delete [-p ]... + get [-p ]... [-o ] + list [-p ]... [-o ] + regions + get [-p ]... [-o ] + list [-p ]... [-o ] + routes + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + snapshots + delete [-p ]... [-o ] + get [-p ]... [-o ] + list [-p ]... [-o ] + target-http-proxies + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + set-url-map (-r )... [-p ]... [-o ] + target-instances + aggregated-list [-p ]... [-o ] + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + target-pools + add-health-check (-r )... [-p ]... [-o ] + add-instance (-r )... [-p ]... [-o ] + aggregated-list [-p ]... [-o ] + delete [-p ]... [-o ] + get [-p ]... [-o ] + get-health (-r )... [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + remove-health-check (-r )... [-p ]... [-o ] + remove-instance (-r )... [-p ]... [-o ] + set-backup (-r )... [-p ]... [-o ] + target-vpn-gateways + aggregated-list [-p ]... [-o ] + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + url-maps + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + validate (-r )... [-p ]... [-o ] + vpn-tunnels + aggregated-list [-p ]... [-o ] + delete [-p ]... [-o ] + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + zone-operations + delete [-p ]... + get [-p ]... [-o ] + list [-p ]... [-o ] + zones + get [-p ]... [-o ] + list [-p ]... [-o ] compute1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_compute1_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/compute1-cli/mkdocs.yml b/gen/compute1-cli/mkdocs.yml index 6d94e9211b..395f68bf21 100644 --- a/gen/compute1-cli/mkdocs.yml +++ b/gen/compute1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: compute v0.1.0+20150326 +site_name: compute v0.2.0+20150326 site_url: http://byron.github.io/google-apis-rs/google-compute1-cli site_description: Write integrating applications with bcore diff --git a/gen/compute1-cli/src/cmn.rs b/gen/compute1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/compute1-cli/src/cmn.rs +++ b/gen/compute1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/compute1-cli/src/main.rs b/gen/compute1-cli/src/main.rs index dbe435f712..68614a3a22 100644 --- a/gen/compute1-cli/src/main.rs +++ b/gen/compute1-cli/src/main.rs @@ -2,212 +2,53 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_compute1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - compute1 [options] addresses aggregated-list [-p ...] [-o ] - compute1 [options] addresses delete
[-p ...] [-o ] - compute1 [options] addresses get
[-p ...] [-o ] - compute1 [options] addresses insert -r ... [-p ...] [-o ] - compute1 [options] addresses list [-p ...] [-o ] - compute1 [options] backend-services delete [-p ...] [-o ] - compute1 [options] backend-services get [-p ...] [-o ] - compute1 [options] backend-services get-health -r ... [-p ...] [-o ] - compute1 [options] backend-services insert -r ... [-p ...] [-o ] - compute1 [options] backend-services list [-p ...] [-o ] - compute1 [options] backend-services patch -r ... [-p ...] [-o ] - compute1 [options] backend-services update -r ... [-p ...] [-o ] - compute1 [options] disk-types aggregated-list [-p ...] [-o ] - compute1 [options] disk-types get [-p ...] [-o ] - compute1 [options] disk-types list [-p ...] [-o ] - compute1 [options] disks aggregated-list [-p ...] [-o ] - compute1 [options] disks create-snapshot -r ... [-p ...] [-o ] - compute1 [options] disks delete [-p ...] [-o ] - compute1 [options] disks get [-p ...] [-o ] - compute1 [options] disks insert -r ... [-p ...] [-o ] - compute1 [options] disks list [-p ...] [-o ] - compute1 [options] firewalls delete [-p ...] [-o ] - compute1 [options] firewalls get [-p ...] [-o ] - compute1 [options] firewalls insert -r ... [-p ...] [-o ] - compute1 [options] firewalls list [-p ...] [-o ] - compute1 [options] firewalls patch -r ... [-p ...] [-o ] - compute1 [options] firewalls update -r ... [-p ...] [-o ] - compute1 [options] forwarding-rules aggregated-list [-p ...] [-o ] - compute1 [options] forwarding-rules delete [-p ...] [-o ] - compute1 [options] forwarding-rules get [-p ...] [-o ] - compute1 [options] forwarding-rules insert -r ... [-p ...] [-o ] - compute1 [options] forwarding-rules list [-p ...] [-o ] - compute1 [options] forwarding-rules set-target -r ... [-p ...] [-o ] - compute1 [options] global-addresses delete
[-p ...] [-o ] - compute1 [options] global-addresses get
[-p ...] [-o ] - compute1 [options] global-addresses insert -r ... [-p ...] [-o ] - compute1 [options] global-addresses list [-p ...] [-o ] - compute1 [options] global-forwarding-rules delete [-p ...] [-o ] - compute1 [options] global-forwarding-rules get [-p ...] [-o ] - compute1 [options] global-forwarding-rules insert -r ... [-p ...] [-o ] - compute1 [options] global-forwarding-rules list [-p ...] [-o ] - compute1 [options] global-forwarding-rules set-target -r ... [-p ...] [-o ] - compute1 [options] global-operations aggregated-list [-p ...] [-o ] - compute1 [options] global-operations delete [-p ...] - compute1 [options] global-operations get [-p ...] [-o ] - compute1 [options] global-operations list [-p ...] [-o ] - compute1 [options] http-health-checks delete [-p ...] [-o ] - compute1 [options] http-health-checks get [-p ...] [-o ] - compute1 [options] http-health-checks insert -r ... [-p ...] [-o ] - compute1 [options] http-health-checks list [-p ...] [-o ] - compute1 [options] http-health-checks patch -r ... [-p ...] [-o ] - compute1 [options] http-health-checks update -r ... [-p ...] [-o ] - compute1 [options] images delete [-p ...] [-o ] - compute1 [options] images deprecate -r ... [-p ...] [-o ] - compute1 [options] images get [-p ...] [-o ] - compute1 [options] images insert -r ... [-p ...] [-o ] - compute1 [options] images list [-p ...] [-o ] - compute1 [options] instance-templates delete [-p ...] [-o ] - compute1 [options] instance-templates get [-p ...] [-o ] - compute1 [options] instance-templates insert -r ... [-p ...] [-o ] - compute1 [options] instance-templates list [-p ...] [-o ] - compute1 [options] instances add-access-config -r ... [-p ...] [-o ] - compute1 [options] instances aggregated-list [-p ...] [-o ] - compute1 [options] instances attach-disk -r ... [-p ...] [-o ] - compute1 [options] instances delete [-p ...] [-o ] - compute1 [options] instances delete-access-config [-p ...] [-o ] - compute1 [options] instances detach-disk [-p ...] [-o ] - compute1 [options] instances get [-p ...] [-o ] - compute1 [options] instances get-serial-port-output [-p ...] [-o ] - compute1 [options] instances insert -r ... [-p ...] [-o ] - compute1 [options] instances list [-p ...] [-o ] - compute1 [options] instances reset [-p ...] [-o ] - compute1 [options] instances set-disk-auto-delete [-p ...] [-o ] - compute1 [options] instances set-metadata -r ... [-p ...] [-o ] - compute1 [options] instances set-scheduling -r ... [-p ...] [-o ] - compute1 [options] instances set-tags -r ... [-p ...] [-o ] - compute1 [options] instances start [-p ...] [-o ] - compute1 [options] instances stop [-p ...] [-o ] - compute1 [options] licenses get [-p ...] [-o ] - compute1 [options] machine-types aggregated-list [-p ...] [-o ] - compute1 [options] machine-types get [-p ...] [-o ] - compute1 [options] machine-types list [-p ...] [-o ] - compute1 [options] networks delete [-p ...] [-o ] - compute1 [options] networks get [-p ...] [-o ] - compute1 [options] networks insert -r ... [-p ...] [-o ] - compute1 [options] networks list [-p ...] [-o ] - compute1 [options] projects get [-p ...] [-o ] - compute1 [options] projects move-disk -r ... [-p ...] [-o ] - compute1 [options] projects move-instance -r ... [-p ...] [-o ] - compute1 [options] projects set-common-instance-metadata -r ... [-p ...] [-o ] - compute1 [options] projects set-usage-export-bucket -r ... [-p ...] [-o ] - compute1 [options] region-operations delete [-p ...] - compute1 [options] region-operations get [-p ...] [-o ] - compute1 [options] region-operations list [-p ...] [-o ] - compute1 [options] regions get [-p ...] [-o ] - compute1 [options] regions list [-p ...] [-o ] - compute1 [options] routes delete [-p ...] [-o ] - compute1 [options] routes get [-p ...] [-o ] - compute1 [options] routes insert -r ... [-p ...] [-o ] - compute1 [options] routes list [-p ...] [-o ] - compute1 [options] snapshots delete [-p ...] [-o ] - compute1 [options] snapshots get [-p ...] [-o ] - compute1 [options] snapshots list [-p ...] [-o ] - compute1 [options] target-http-proxies delete [-p ...] [-o ] - compute1 [options] target-http-proxies get [-p ...] [-o ] - compute1 [options] target-http-proxies insert -r ... [-p ...] [-o ] - compute1 [options] target-http-proxies list [-p ...] [-o ] - compute1 [options] target-http-proxies set-url-map -r ... [-p ...] [-o ] - compute1 [options] target-instances aggregated-list [-p ...] [-o ] - compute1 [options] target-instances delete [-p ...] [-o ] - compute1 [options] target-instances get [-p ...] [-o ] - compute1 [options] target-instances insert -r ... [-p ...] [-o ] - compute1 [options] target-instances list [-p ...] [-o ] - compute1 [options] target-pools add-health-check -r ... [-p ...] [-o ] - compute1 [options] target-pools add-instance -r ... [-p ...] [-o ] - compute1 [options] target-pools aggregated-list [-p ...] [-o ] - compute1 [options] target-pools delete [-p ...] [-o ] - compute1 [options] target-pools get [-p ...] [-o ] - compute1 [options] target-pools get-health -r ... [-p ...] [-o ] - compute1 [options] target-pools insert -r ... [-p ...] [-o ] - compute1 [options] target-pools list [-p ...] [-o ] - compute1 [options] target-pools remove-health-check -r ... [-p ...] [-o ] - compute1 [options] target-pools remove-instance -r ... [-p ...] [-o ] - compute1 [options] target-pools set-backup -r ... [-p ...] [-o ] - compute1 [options] target-vpn-gateways aggregated-list [-p ...] [-o ] - compute1 [options] target-vpn-gateways delete [-p ...] [-o ] - compute1 [options] target-vpn-gateways get [-p ...] [-o ] - compute1 [options] target-vpn-gateways insert -r ... [-p ...] [-o ] - compute1 [options] target-vpn-gateways list [-p ...] [-o ] - compute1 [options] url-maps delete [-p ...] [-o ] - compute1 [options] url-maps get [-p ...] [-o ] - compute1 [options] url-maps insert -r ... [-p ...] [-o ] - compute1 [options] url-maps list [-p ...] [-o ] - compute1 [options] url-maps patch -r ... [-p ...] [-o ] - compute1 [options] url-maps update -r ... [-p ...] [-o ] - compute1 [options] url-maps validate -r ... [-p ...] [-o ] - compute1 [options] vpn-tunnels aggregated-list [-p ...] [-o ] - compute1 [options] vpn-tunnels delete [-p ...] [-o ] - compute1 [options] vpn-tunnels get [-p ...] [-o ] - compute1 [options] vpn-tunnels insert -r ... [-p ...] [-o ] - compute1 [options] vpn-tunnels list [-p ...] [-o ] - compute1 [options] zone-operations delete [-p ...] - compute1 [options] zone-operations get [-p ...] [-o ] - compute1 [options] zone-operations list [-p ...] [-o ] - compute1 [options] zones get [-p ...] [-o ] - compute1 [options] zones list [-p ...] [-o ] - compute1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_compute1_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Compute>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _addresses_aggregated_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.addresses().aggregated_list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _addresses_aggregated_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.addresses().aggregated_list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -219,144 +60,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _addresses_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.addresses().delete(&self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_address); - for parg in self.opt.arg_v.iter() { + fn _addresses_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.addresses().delete(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("address").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _addresses_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.addresses().get(&self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_address); - for parg in self.opt.arg_v.iter() { + fn _addresses_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.addresses().get(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("address").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _addresses_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _addresses_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Address::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -405,58 +258,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "creation-timestamp", "description", "id", "kind", "name", "region", "self-link", "status", "users"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.addresses().insert(request, &self.opt.arg_project, &self.opt.arg_region); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.addresses().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _addresses_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.addresses().list(&self.opt.arg_project, &self.opt.arg_region); - for parg in self.opt.arg_v.iter() { + fn _addresses_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.addresses().list(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -468,144 +326,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _backend_services_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.backend_services().delete(&self.opt.arg_project, &self.opt.arg_backend_service); - for parg in self.opt.arg_v.iter() { + fn _backend_services_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.backend_services().delete(opt.value_of("project").unwrap_or(""), opt.value_of("backend-service").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _backend_services_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.backend_services().get(&self.opt.arg_project, &self.opt.arg_backend_service); - for parg in self.opt.arg_v.iter() { + fn _backend_services_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.backend_services().get(opt.value_of("project").unwrap_or(""), opt.value_of("backend-service").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _backend_services_get_health(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _backend_services_get_health(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ResourceGroupReference::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -624,60 +494,65 @@ impl Engine { request.group = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["group"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.backend_services().get_health(request, &self.opt.arg_project, &self.opt.arg_backend_service); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.backend_services().get_health(request, opt.value_of("project").unwrap_or(""), opt.value_of("backend-service").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _backend_services_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _backend_services_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::BackendService::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -732,58 +607,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "description", "fingerprint", "health-checks", "id", "kind", "name", "port", "port-name", "protocol", "self-link", "timeout-sec"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.backend_services().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.backend_services().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _backend_services_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.backend_services().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _backend_services_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.backend_services().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -795,52 +675,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _backend_services_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _backend_services_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::BackendService::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -895,60 +779,65 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "description", "fingerprint", "health-checks", "id", "kind", "name", "port", "port-name", "protocol", "self-link", "timeout-sec"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.backend_services().patch(request, &self.opt.arg_project, &self.opt.arg_backend_service); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.backend_services().patch(request, opt.value_of("project").unwrap_or(""), opt.value_of("backend-service").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _backend_services_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _backend_services_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::BackendService::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1003,58 +892,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "description", "fingerprint", "health-checks", "id", "kind", "name", "port", "port-name", "protocol", "self-link", "timeout-sec"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.backend_services().update(request, &self.opt.arg_project, &self.opt.arg_backend_service); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.backend_services().update(request, opt.value_of("project").unwrap_or(""), opt.value_of("backend-service").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _disk_types_aggregated_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.disk_types().aggregated_list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _disk_types_aggregated_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.disk_types().aggregated_list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1066,96 +960,104 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _disk_types_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.disk_types().get(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_disk_type); - for parg in self.opt.arg_v.iter() { + fn _disk_types_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.disk_types().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("disk-type").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _disk_types_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.disk_types().list(&self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + fn _disk_types_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.disk_types().list(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1167,50 +1069,54 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _disks_aggregated_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.disks().aggregated_list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _disks_aggregated_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.disks().aggregated_list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1222,52 +1128,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _disks_create_snapshot(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _disks_create_snapshot(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Snapshot::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1325,152 +1235,165 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "description", "disk-size-gb", "id", "kind", "licenses", "name", "self-link", "source-disk", "source-disk-id", "status", "storage-bytes", "storage-bytes-status"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.disks().create_snapshot(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_disk); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.disks().create_snapshot(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("disk").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _disks_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.disks().delete(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_disk); - for parg in self.opt.arg_v.iter() { + fn _disks_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.disks().delete(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("disk").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _disks_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.disks().get(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_disk); - for parg in self.opt.arg_v.iter() { + fn _disks_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.disks().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("disk").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _disks_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _disks_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Disk::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1537,61 +1460,66 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "description", "id", "kind", "licenses", "name", "options", "self-link", "size-gb", "source-image", "source-image-id", "source-snapshot", "source-snapshot-id", "status", "type", "zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.disks().insert(request, &self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.disks().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source-image" => { call = call.source_image(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source-image"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _disks_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.disks().list(&self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + fn _disks_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.disks().list(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1603,144 +1531,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _firewalls_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.firewalls().delete(&self.opt.arg_project, &self.opt.arg_firewall); - for parg in self.opt.arg_v.iter() { + fn _firewalls_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.firewalls().delete(opt.value_of("project").unwrap_or(""), opt.value_of("firewall").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _firewalls_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.firewalls().get(&self.opt.arg_project, &self.opt.arg_firewall); - for parg in self.opt.arg_v.iter() { + fn _firewalls_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.firewalls().get(opt.value_of("project").unwrap_or(""), opt.value_of("firewall").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _firewalls_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _firewalls_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Firewall::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1795,58 +1735,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "description", "id", "kind", "name", "network", "self-link", "source-ranges", "source-tags", "target-tags"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.firewalls().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.firewalls().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _firewalls_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.firewalls().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _firewalls_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.firewalls().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1858,52 +1803,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _firewalls_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _firewalls_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Firewall::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1958,60 +1907,65 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "description", "id", "kind", "name", "network", "self-link", "source-ranges", "source-tags", "target-tags"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.firewalls().patch(request, &self.opt.arg_project, &self.opt.arg_firewall); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.firewalls().patch(request, opt.value_of("project").unwrap_or(""), opt.value_of("firewall").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _firewalls_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _firewalls_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Firewall::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2066,58 +2020,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "description", "id", "kind", "name", "network", "self-link", "source-ranges", "source-tags", "target-tags"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.firewalls().update(request, &self.opt.arg_project, &self.opt.arg_firewall); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.firewalls().update(request, opt.value_of("project").unwrap_or(""), opt.value_of("firewall").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _forwarding_rules_aggregated_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.forwarding_rules().aggregated_list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _forwarding_rules_aggregated_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.forwarding_rules().aggregated_list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2129,144 +2088,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _forwarding_rules_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.forwarding_rules().delete(&self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_forwarding_rule); - for parg in self.opt.arg_v.iter() { + fn _forwarding_rules_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.forwarding_rules().delete(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("forwarding-rule").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _forwarding_rules_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.forwarding_rules().get(&self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_forwarding_rule); - for parg in self.opt.arg_v.iter() { + fn _forwarding_rules_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.forwarding_rules().get(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("forwarding-rule").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _forwarding_rules_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _forwarding_rules_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ForwardingRule::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2315,58 +2286,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ip-address", "ip-protocol", "creation-timestamp", "description", "id", "kind", "name", "port-range", "region", "self-link", "target"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.forwarding_rules().insert(request, &self.opt.arg_project, &self.opt.arg_region); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.forwarding_rules().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _forwarding_rules_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.forwarding_rules().list(&self.opt.arg_project, &self.opt.arg_region); - for parg in self.opt.arg_v.iter() { + fn _forwarding_rules_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.forwarding_rules().list(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2378,52 +2354,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _forwarding_rules_set_target(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _forwarding_rules_set_target(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TargetReference::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2442,152 +2422,165 @@ impl Engine { request.target = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["target"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.forwarding_rules().set_target(request, &self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_forwarding_rule); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.forwarding_rules().set_target(request, opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("forwarding-rule").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _global_addresses_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.global_addresses().delete(&self.opt.arg_project, &self.opt.arg_address); - for parg in self.opt.arg_v.iter() { + fn _global_addresses_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.global_addresses().delete(opt.value_of("project").unwrap_or(""), opt.value_of("address").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _global_addresses_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.global_addresses().get(&self.opt.arg_project, &self.opt.arg_address); - for parg in self.opt.arg_v.iter() { + fn _global_addresses_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.global_addresses().get(opt.value_of("project").unwrap_or(""), opt.value_of("address").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _global_addresses_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _global_addresses_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Address::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2636,58 +2629,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "creation-timestamp", "description", "id", "kind", "name", "region", "self-link", "status", "users"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.global_addresses().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.global_addresses().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _global_addresses_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.global_addresses().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _global_addresses_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.global_addresses().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2699,144 +2697,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _global_forwarding_rules_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.global_forwarding_rules().delete(&self.opt.arg_project, &self.opt.arg_forwarding_rule); - for parg in self.opt.arg_v.iter() { + fn _global_forwarding_rules_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.global_forwarding_rules().delete(opt.value_of("project").unwrap_or(""), opt.value_of("forwarding-rule").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _global_forwarding_rules_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.global_forwarding_rules().get(&self.opt.arg_project, &self.opt.arg_forwarding_rule); - for parg in self.opt.arg_v.iter() { + fn _global_forwarding_rules_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.global_forwarding_rules().get(opt.value_of("project").unwrap_or(""), opt.value_of("forwarding-rule").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _global_forwarding_rules_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _global_forwarding_rules_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ForwardingRule::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2885,58 +2895,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ip-address", "ip-protocol", "creation-timestamp", "description", "id", "kind", "name", "port-range", "region", "self-link", "target"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.global_forwarding_rules().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.global_forwarding_rules().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _global_forwarding_rules_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.global_forwarding_rules().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _global_forwarding_rules_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.global_forwarding_rules().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2948,52 +2963,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _global_forwarding_rules_set_target(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _global_forwarding_rules_set_target(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TargetReference::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3012,58 +3031,63 @@ impl Engine { request.target = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["target"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.global_forwarding_rules().set_target(request, &self.opt.arg_project, &self.opt.arg_forwarding_rule); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.global_forwarding_rules().set_target(request, opt.value_of("project").unwrap_or(""), opt.value_of("forwarding-rule").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _global_operations_aggregated_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.global_operations().aggregated_list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _global_operations_aggregated_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.global_operations().aggregated_list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -3075,140 +3099,147 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _global_operations_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.global_operations().delete(&self.opt.arg_project, &self.opt.arg_operation); - for parg in self.opt.arg_v.iter() { + fn _global_operations_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.global_operations().delete(opt.value_of("project").unwrap_or(""), opt.value_of("operation").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _global_operations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.global_operations().get(&self.opt.arg_project, &self.opt.arg_operation); - for parg in self.opt.arg_v.iter() { + fn _global_operations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.global_operations().get(opt.value_of("project").unwrap_or(""), opt.value_of("operation").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _global_operations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.global_operations().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _global_operations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.global_operations().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -3220,144 +3251,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _http_health_checks_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.http_health_checks().delete(&self.opt.arg_project, &self.opt.arg_http_health_check); - for parg in self.opt.arg_v.iter() { + fn _http_health_checks_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.http_health_checks().delete(opt.value_of("project").unwrap_or(""), opt.value_of("http-health-check").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _http_health_checks_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.http_health_checks().get(&self.opt.arg_project, &self.opt.arg_http_health_check); - for parg in self.opt.arg_v.iter() { + fn _http_health_checks_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.http_health_checks().get(opt.value_of("project").unwrap_or(""), opt.value_of("http-health-check").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _http_health_checks_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _http_health_checks_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::HttpHealthCheck::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3412,58 +3455,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["check-interval-sec", "creation-timestamp", "description", "healthy-threshold", "host", "id", "kind", "name", "port", "request-path", "self-link", "timeout-sec", "unhealthy-threshold"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.http_health_checks().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.http_health_checks().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _http_health_checks_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.http_health_checks().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _http_health_checks_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.http_health_checks().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -3475,52 +3523,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _http_health_checks_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _http_health_checks_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::HttpHealthCheck::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3575,60 +3627,65 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["check-interval-sec", "creation-timestamp", "description", "healthy-threshold", "host", "id", "kind", "name", "port", "request-path", "self-link", "timeout-sec", "unhealthy-threshold"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.http_health_checks().patch(request, &self.opt.arg_project, &self.opt.arg_http_health_check); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.http_health_checks().patch(request, opt.value_of("project").unwrap_or(""), opt.value_of("http-health-check").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _http_health_checks_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _http_health_checks_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::HttpHealthCheck::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3683,106 +3740,115 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["check-interval-sec", "creation-timestamp", "description", "healthy-threshold", "host", "id", "kind", "name", "port", "request-path", "self-link", "timeout-sec", "unhealthy-threshold"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.http_health_checks().update(request, &self.opt.arg_project, &self.opt.arg_http_health_check); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.http_health_checks().update(request, opt.value_of("project").unwrap_or(""), opt.value_of("http-health-check").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _images_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.images().delete(&self.opt.arg_project, &self.opt.arg_image); - for parg in self.opt.arg_v.iter() { + fn _images_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.images().delete(opt.value_of("project").unwrap_or(""), opt.value_of("image").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _images_deprecate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _images_deprecate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::DeprecationStatus::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3813,106 +3879,115 @@ impl Engine { request.replacement = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["deleted", "deprecated", "obsolete", "replacement", "state"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.images().deprecate(request, &self.opt.arg_project, &self.opt.arg_image); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.images().deprecate(request, opt.value_of("project").unwrap_or(""), opt.value_of("image").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _images_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.images().get(&self.opt.arg_project, &self.opt.arg_image); - for parg in self.opt.arg_v.iter() { + fn _images_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.images().get(opt.value_of("project").unwrap_or(""), opt.value_of("image").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _images_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _images_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Image::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4024,58 +4099,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["archive-size-bytes", "container-type", "creation-timestamp", "deleted", "deprecated", "description", "disk-size-gb", "id", "kind", "licenses", "name", "obsolete", "raw-disk", "replacement", "self-link", "sha1-checksum", "source", "source-disk", "source-disk-id", "source-type", "state", "status"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.images().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.images().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _images_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.images().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _images_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.images().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -4087,144 +4167,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instance_templates_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.instance_templates().delete(&self.opt.arg_project, &self.opt.arg_instance_template); - for parg in self.opt.arg_v.iter() { + fn _instance_templates_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instance_templates().delete(opt.value_of("project").unwrap_or(""), opt.value_of("instance-template").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instance_templates_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.instance_templates().get(&self.opt.arg_project, &self.opt.arg_instance_template); - for parg in self.opt.arg_v.iter() { + fn _instance_templates_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instance_templates().get(opt.value_of("project").unwrap_or(""), opt.value_of("instance-template").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instance_templates_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _instance_templates_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InstanceTemplate::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4326,58 +4418,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["automatic-restart", "can-ip-forward", "creation-timestamp", "description", "fingerprint", "id", "items", "kind", "machine-type", "metadata", "name", "on-host-maintenance", "properties", "scheduling", "self-link", "tags"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instance_templates().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instance_templates().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instance_templates_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.instance_templates().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _instance_templates_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instance_templates().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -4389,52 +4486,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_add_access_config(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _instances_add_access_config(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AccessConfig::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4462,58 +4563,63 @@ impl Engine { request.nat_ip = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind", "name", "nat-ip", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instances().add_access_config(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance, &self.opt.arg_network_interface); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instances().add_access_config(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance").unwrap_or(""), opt.value_of("network-interface").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_aggregated_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.instances().aggregated_list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _instances_aggregated_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().aggregated_list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -4525,52 +4631,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_attach_disk(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _instances_attach_disk(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AttachedDisk::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4649,293 +4759,318 @@ impl Engine { request.source = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["auto-delete", "boot", "device-name", "disk-name", "disk-size-gb", "disk-type", "index", "initialize-params", "interface", "kind", "licenses", "mode", "source", "source-image", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instances().attach_disk(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instances().attach_disk(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.instances().delete(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _instances_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().delete(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_delete_access_config(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.instances().delete_access_config(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance, &self.opt.arg_access_config, &self.opt.arg_network_interface); - for parg in self.opt.arg_v.iter() { + fn _instances_delete_access_config(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().delete_access_config(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance").unwrap_or(""), opt.value_of("access-config").unwrap_or(""), opt.value_of("network-interface").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_detach_disk(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.instances().detach_disk(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance, &self.opt.arg_device_name); - for parg in self.opt.arg_v.iter() { + fn _instances_detach_disk(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().detach_disk(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance").unwrap_or(""), opt.value_of("device-name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.instances().get(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _instances_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_get_serial_port_output(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.instances().get_serial_port_output(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _instances_get_serial_port_output(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().get_serial_port_output(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "port" => { call = call.port(arg_from_str(value.unwrap_or("-0"), err, "port", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["port"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _instances_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Instance::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -5038,58 +5173,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["automatic-restart", "can-ip-forward", "cpu-platform", "creation-timestamp", "description", "fingerprint", "id", "items", "kind", "machine-type", "metadata", "name", "on-host-maintenance", "scheduling", "self-link", "status", "status-message", "tags", "zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instances().insert(request, &self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instances().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.instances().list(&self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + fn _instances_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().list(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -5101,145 +5241,157 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_reset(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.instances().reset(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _instances_reset(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().reset(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_set_disk_auto_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let auto_delete: bool = arg_from_str(&self.opt.arg_auto_delete, err, "", "boolean"); - let mut call = self.hub.instances().set_disk_auto_delete(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance, auto_delete, &self.opt.arg_device_name); - for parg in self.opt.arg_v.iter() { + fn _instances_set_disk_auto_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let auto_delete: bool = arg_from_str(&opt.value_of("auto-delete").unwrap_or(""), err, "", "boolean"); + let mut call = self.hub.instances().set_disk_auto_delete(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance").unwrap_or(""), auto_delete, opt.value_of("device-name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_set_metadata(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _instances_set_metadata(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Metadata::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -5261,60 +5413,65 @@ impl Engine { request.fingerprint = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["fingerprint", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instances().set_metadata(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instances().set_metadata(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_set_scheduling(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _instances_set_scheduling(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Scheduling::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -5336,60 +5493,65 @@ impl Engine { request.on_host_maintenance = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["automatic-restart", "on-host-maintenance"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instances().set_scheduling(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instances().set_scheduling(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_set_tags(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _instances_set_tags(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Tags::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -5414,196 +5576,213 @@ impl Engine { request.fingerprint = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["fingerprint", "items"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instances().set_tags(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instances().set_tags(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_start(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.instances().start(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _instances_start(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().start(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_stop(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.instances().stop(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _instances_stop(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().stop(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _licenses_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.licenses().get(&self.opt.arg_project, &self.opt.arg_license); - for parg in self.opt.arg_v.iter() { + fn _licenses_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.licenses().get(opt.value_of("project").unwrap_or(""), opt.value_of("license").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _machine_types_aggregated_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.machine_types().aggregated_list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _machine_types_aggregated_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.machine_types().aggregated_list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -5615,96 +5794,104 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _machine_types_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.machine_types().get(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_machine_type); - for parg in self.opt.arg_v.iter() { + fn _machine_types_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.machine_types().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("machine-type").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _machine_types_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.machine_types().list(&self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + fn _machine_types_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.machine_types().list(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -5716,144 +5903,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _networks_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.networks().delete(&self.opt.arg_project, &self.opt.arg_network); - for parg in self.opt.arg_v.iter() { + fn _networks_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.networks().delete(opt.value_of("project").unwrap_or(""), opt.value_of("network").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _networks_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.networks().get(&self.opt.arg_project, &self.opt.arg_network); - for parg in self.opt.arg_v.iter() { + fn _networks_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.networks().get(opt.value_of("project").unwrap_or(""), opt.value_of("network").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _networks_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _networks_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Network::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -5893,58 +6092,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["i-pv4-range", "creation-timestamp", "description", "gateway-i-pv4", "id", "kind", "name", "self-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.networks().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.networks().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _networks_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.networks().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _networks_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.networks().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -5956,98 +6160,106 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.projects().get(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _projects_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().get(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_move_disk(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _projects_move_disk(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::DiskMoveRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -6069,60 +6281,65 @@ impl Engine { request.destination_zone = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["destination-zone", "target-disk"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().move_disk(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().move_disk(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_move_instance(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _projects_move_instance(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InstanceMoveRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -6144,60 +6361,65 @@ impl Engine { request.destination_zone = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["destination-zone", "target-instance"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().move_instance(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().move_instance(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_set_common_instance_metadata(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _projects_set_common_instance_metadata(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Metadata::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -6219,60 +6441,65 @@ impl Engine { request.fingerprint = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["fingerprint", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().set_common_instance_metadata(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().set_common_instance_metadata(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_set_usage_export_bucket(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _projects_set_usage_export_bucket(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UsageExportLocation::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -6294,148 +6521,156 @@ impl Engine { request.report_name_prefix = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket-name", "report-name-prefix"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().set_usage_export_bucket(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().set_usage_export_bucket(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _region_operations_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.region_operations().delete(&self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_operation); - for parg in self.opt.arg_v.iter() { + fn _region_operations_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.region_operations().delete(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("operation").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _region_operations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.region_operations().get(&self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_operation); - for parg in self.opt.arg_v.iter() { + fn _region_operations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.region_operations().get(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("operation").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _region_operations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.region_operations().list(&self.opt.arg_project, &self.opt.arg_region); - for parg in self.opt.arg_v.iter() { + fn _region_operations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.region_operations().list(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -6447,96 +6682,104 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _regions_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.regions().get(&self.opt.arg_project, &self.opt.arg_region); - for parg in self.opt.arg_v.iter() { + fn _regions_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.regions().get(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _regions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.regions().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _regions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.regions().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -6548,144 +6791,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _routes_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.routes().delete(&self.opt.arg_project, &self.opt.arg_route); - for parg in self.opt.arg_v.iter() { + fn _routes_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.routes().delete(opt.value_of("project").unwrap_or(""), opt.value_of("route").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _routes_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.routes().get(&self.opt.arg_project, &self.opt.arg_route); - for parg in self.opt.arg_v.iter() { + fn _routes_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.routes().get(opt.value_of("project").unwrap_or(""), opt.value_of("route").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _routes_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _routes_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Route::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -6749,58 +7004,63 @@ impl Engine { request.network = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "description", "dest-range", "id", "kind", "name", "network", "next-hop-gateway", "next-hop-instance", "next-hop-ip", "next-hop-network", "next-hop-vpn-tunnel", "priority", "self-link", "tags"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.routes().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.routes().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _routes_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.routes().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _routes_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.routes().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -6812,142 +7072,154 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _snapshots_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.snapshots().delete(&self.opt.arg_project, &self.opt.arg_snapshot); - for parg in self.opt.arg_v.iter() { + fn _snapshots_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.snapshots().delete(opt.value_of("project").unwrap_or(""), opt.value_of("snapshot").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _snapshots_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.snapshots().get(&self.opt.arg_project, &self.opt.arg_snapshot); - for parg in self.opt.arg_v.iter() { + fn _snapshots_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.snapshots().get(opt.value_of("project").unwrap_or(""), opt.value_of("snapshot").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _snapshots_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.snapshots().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _snapshots_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.snapshots().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -6959,144 +7231,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_http_proxies_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_http_proxies().delete(&self.opt.arg_project, &self.opt.arg_target_http_proxy); - for parg in self.opt.arg_v.iter() { + fn _target_http_proxies_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_http_proxies().delete(opt.value_of("project").unwrap_or(""), opt.value_of("target-http-proxy").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_http_proxies_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_http_proxies().get(&self.opt.arg_project, &self.opt.arg_target_http_proxy); - for parg in self.opt.arg_v.iter() { + fn _target_http_proxies_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_http_proxies().get(opt.value_of("project").unwrap_or(""), opt.value_of("target-http-proxy").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_http_proxies_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _target_http_proxies_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TargetHttpProxy::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -7133,58 +7417,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "description", "id", "kind", "name", "self-link", "url-map"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.target_http_proxies().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.target_http_proxies().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_http_proxies_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_http_proxies().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _target_http_proxies_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_http_proxies().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -7196,52 +7485,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_http_proxies_set_url_map(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _target_http_proxies_set_url_map(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UrlMapReference::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -7260,58 +7553,63 @@ impl Engine { request.url_map = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["url-map"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.target_http_proxies().set_url_map(request, &self.opt.arg_project, &self.opt.arg_target_http_proxy); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.target_http_proxies().set_url_map(request, opt.value_of("project").unwrap_or(""), opt.value_of("target-http-proxy").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_instances_aggregated_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_instances().aggregated_list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _target_instances_aggregated_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_instances().aggregated_list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -7323,144 +7621,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_instances_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_instances().delete(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_target_instance); - for parg in self.opt.arg_v.iter() { + fn _target_instances_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_instances().delete(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("target-instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_instances_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_instances().get(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_target_instance); - for parg in self.opt.arg_v.iter() { + fn _target_instances_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_instances().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("target-instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_instances_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _target_instances_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TargetInstance::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -7503,58 +7813,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "description", "id", "instance", "kind", "name", "nat-policy", "self-link", "zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.target_instances().insert(request, &self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.target_instances().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_instances_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_instances().list(&self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + fn _target_instances_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_instances().list(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -7566,52 +7881,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_pools_add_health_check(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _target_pools_add_health_check(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TargetPoolsAddHealthCheckRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -7627,60 +7946,65 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.target_pools().add_health_check(request, &self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_target_pool); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.target_pools().add_health_check(request, opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("target-pool").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_pools_add_instance(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _target_pools_add_instance(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TargetPoolsAddInstanceRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -7696,58 +8020,63 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.target_pools().add_instance(request, &self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_target_pool); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.target_pools().add_instance(request, opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("target-pool").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_pools_aggregated_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_pools().aggregated_list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _target_pools_aggregated_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_pools().aggregated_list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -7759,144 +8088,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_pools_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_pools().delete(&self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_target_pool); - for parg in self.opt.arg_v.iter() { + fn _target_pools_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_pools().delete(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("target-pool").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_pools_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_pools().get(&self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_target_pool); - for parg in self.opt.arg_v.iter() { + fn _target_pools_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_pools().get(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("target-pool").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_pools_get_health(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _target_pools_get_health(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InstanceReference::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -7915,60 +8256,65 @@ impl Engine { request.instance = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["instance"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.target_pools().get_health(request, &self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_target_pool); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.target_pools().get_health(request, opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("target-pool").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_pools_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _target_pools_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TargetPool::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -8026,58 +8372,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["backup-pool", "creation-timestamp", "description", "failover-ratio", "health-checks", "id", "instances", "kind", "name", "region", "self-link", "session-affinity"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.target_pools().insert(request, &self.opt.arg_project, &self.opt.arg_region); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.target_pools().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_pools_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_pools().list(&self.opt.arg_project, &self.opt.arg_region); - for parg in self.opt.arg_v.iter() { + fn _target_pools_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_pools().list(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -8089,52 +8440,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_pools_remove_health_check(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _target_pools_remove_health_check(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TargetPoolsRemoveHealthCheckRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -8150,60 +8505,65 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.target_pools().remove_health_check(request, &self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_target_pool); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.target_pools().remove_health_check(request, opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("target-pool").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_pools_remove_instance(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _target_pools_remove_instance(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TargetPoolsRemoveInstanceRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -8219,60 +8579,65 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.target_pools().remove_instance(request, &self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_target_pool); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.target_pools().remove_instance(request, opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("target-pool").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_pools_set_backup(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _target_pools_set_backup(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TargetReference::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -8291,61 +8656,66 @@ impl Engine { request.target = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["target"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.target_pools().set_backup(request, &self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_target_pool); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.target_pools().set_backup(request, opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("target-pool").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "failover-ratio" => { call = call.failover_ratio(arg_from_str(value.unwrap_or("0.0"), err, "failover-ratio", "number")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["failover-ratio"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_vpn_gateways_aggregated_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_vpn_gateways().aggregated_list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _target_vpn_gateways_aggregated_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_vpn_gateways().aggregated_list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -8357,144 +8727,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_vpn_gateways_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_vpn_gateways().delete(&self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_target_vpn_gateway); - for parg in self.opt.arg_v.iter() { + fn _target_vpn_gateways_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_vpn_gateways().delete(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("target-vpn-gateway").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_vpn_gateways_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_vpn_gateways().get(&self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_target_vpn_gateway); - for parg in self.opt.arg_v.iter() { + fn _target_vpn_gateways_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_vpn_gateways().get(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("target-vpn-gateway").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_vpn_gateways_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _target_vpn_gateways_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TargetVpnGateway::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -8549,58 +8931,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "description", "forwarding-rules", "id", "kind", "name", "network", "region", "self-link", "status", "tunnels"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.target_vpn_gateways().insert(request, &self.opt.arg_project, &self.opt.arg_region); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.target_vpn_gateways().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _target_vpn_gateways_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.target_vpn_gateways().list(&self.opt.arg_project, &self.opt.arg_region); - for parg in self.opt.arg_v.iter() { + fn _target_vpn_gateways_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.target_vpn_gateways().list(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -8612,144 +8999,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _url_maps_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.url_maps().delete(&self.opt.arg_project, &self.opt.arg_url_map); - for parg in self.opt.arg_v.iter() { + fn _url_maps_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.url_maps().delete(opt.value_of("project").unwrap_or(""), opt.value_of("url-map").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _url_maps_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.url_maps().get(&self.opt.arg_project, &self.opt.arg_url_map); - for parg in self.opt.arg_v.iter() { + fn _url_maps_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.url_maps().get(opt.value_of("project").unwrap_or(""), opt.value_of("url-map").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _url_maps_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _url_maps_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UrlMap::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -8789,58 +9188,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "default-service", "description", "fingerprint", "id", "kind", "name", "self-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.url_maps().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.url_maps().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _url_maps_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.url_maps().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _url_maps_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.url_maps().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -8852,52 +9256,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _url_maps_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _url_maps_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UrlMap::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -8937,60 +9345,65 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "default-service", "description", "fingerprint", "id", "kind", "name", "self-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.url_maps().patch(request, &self.opt.arg_project, &self.opt.arg_url_map); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.url_maps().patch(request, opt.value_of("project").unwrap_or(""), opt.value_of("url-map").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _url_maps_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _url_maps_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UrlMap::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -9030,60 +9443,65 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "default-service", "description", "fingerprint", "id", "kind", "name", "self-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.url_maps().update(request, &self.opt.arg_project, &self.opt.arg_url_map); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.url_maps().update(request, opt.value_of("project").unwrap_or(""), opt.value_of("url-map").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _url_maps_validate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _url_maps_validate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UrlMapsValidateRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -9137,58 +9555,63 @@ impl Engine { request.resource.as_mut().unwrap().name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "default-service", "description", "fingerprint", "id", "kind", "name", "resource", "self-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.url_maps().validate(request, &self.opt.arg_project, &self.opt.arg_url_map); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.url_maps().validate(request, opt.value_of("project").unwrap_or(""), opt.value_of("url-map").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _vpn_tunnels_aggregated_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.vpn_tunnels().aggregated_list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _vpn_tunnels_aggregated_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.vpn_tunnels().aggregated_list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -9200,144 +9623,156 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _vpn_tunnels_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.vpn_tunnels().delete(&self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_vpn_tunnel); - for parg in self.opt.arg_v.iter() { + fn _vpn_tunnels_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.vpn_tunnels().delete(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("vpn-tunnel").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _vpn_tunnels_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.vpn_tunnels().get(&self.opt.arg_project, &self.opt.arg_region, &self.opt.arg_vpn_tunnel); - for parg in self.opt.arg_v.iter() { + fn _vpn_tunnels_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.vpn_tunnels().get(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("vpn-tunnel").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _vpn_tunnels_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _vpn_tunnels_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::VpnTunnel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -9401,58 +9836,63 @@ impl Engine { request.ike_networks.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "description", "detailed-status", "id", "ike-networks", "ike-version", "kind", "name", "peer-ip", "region", "self-link", "shared-secret", "shared-secret-hash", "status", "target-vpn-gateway"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.vpn_tunnels().insert(request, &self.opt.arg_project, &self.opt.arg_region); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.vpn_tunnels().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _vpn_tunnels_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.vpn_tunnels().list(&self.opt.arg_project, &self.opt.arg_region); - for parg in self.opt.arg_v.iter() { + fn _vpn_tunnels_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.vpn_tunnels().list(opt.value_of("project").unwrap_or(""), opt.value_of("region").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -9464,140 +9904,147 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_operations_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.zone_operations().delete(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_operation); - for parg in self.opt.arg_v.iter() { + fn _zone_operations_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_operations().delete(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("operation").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _zone_operations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.zone_operations().get(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_operation); - for parg in self.opt.arg_v.iter() { + fn _zone_operations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_operations().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("operation").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_operations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.zone_operations().list(&self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + fn _zone_operations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_operations().list(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -9609,96 +10056,104 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zones_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.zones().get(&self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + fn _zones_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zones().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zones_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.zones().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _zones_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zones().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -9710,503 +10165,745 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_addresses { - if self.opt.cmd_aggregated_list { - call_result = self._addresses_aggregated_list(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._addresses_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._addresses_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._addresses_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._addresses_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("addresses", Some(opt)) => { + match opt.subcommand() { + ("aggregated-list", Some(opt)) => { + call_result = self._addresses_aggregated_list(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._addresses_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._addresses_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._addresses_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._addresses_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("addresses".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("backend-services", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._backend_services_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._backend_services_get(opt, dry_run, &mut err); + }, + ("get-health", Some(opt)) => { + call_result = self._backend_services_get_health(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._backend_services_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._backend_services_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._backend_services_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._backend_services_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("backend-services".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("disk-types", Some(opt)) => { + match opt.subcommand() { + ("aggregated-list", Some(opt)) => { + call_result = self._disk_types_aggregated_list(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._disk_types_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._disk_types_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("disk-types".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("disks", Some(opt)) => { + match opt.subcommand() { + ("aggregated-list", Some(opt)) => { + call_result = self._disks_aggregated_list(opt, dry_run, &mut err); + }, + ("create-snapshot", Some(opt)) => { + call_result = self._disks_create_snapshot(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._disks_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._disks_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._disks_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._disks_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("disks".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("firewalls", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._firewalls_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._firewalls_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._firewalls_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._firewalls_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._firewalls_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._firewalls_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("firewalls".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("forwarding-rules", Some(opt)) => { + match opt.subcommand() { + ("aggregated-list", Some(opt)) => { + call_result = self._forwarding_rules_aggregated_list(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._forwarding_rules_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._forwarding_rules_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._forwarding_rules_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._forwarding_rules_list(opt, dry_run, &mut err); + }, + ("set-target", Some(opt)) => { + call_result = self._forwarding_rules_set_target(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("forwarding-rules".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("global-addresses", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._global_addresses_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._global_addresses_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._global_addresses_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._global_addresses_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("global-addresses".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("global-forwarding-rules", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._global_forwarding_rules_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._global_forwarding_rules_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._global_forwarding_rules_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._global_forwarding_rules_list(opt, dry_run, &mut err); + }, + ("set-target", Some(opt)) => { + call_result = self._global_forwarding_rules_set_target(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("global-forwarding-rules".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("global-operations", Some(opt)) => { + match opt.subcommand() { + ("aggregated-list", Some(opt)) => { + call_result = self._global_operations_aggregated_list(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._global_operations_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._global_operations_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._global_operations_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("global-operations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("http-health-checks", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._http_health_checks_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._http_health_checks_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._http_health_checks_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._http_health_checks_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._http_health_checks_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._http_health_checks_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("http-health-checks".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("images", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._images_delete(opt, dry_run, &mut err); + }, + ("deprecate", Some(opt)) => { + call_result = self._images_deprecate(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._images_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._images_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._images_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("images".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("instance-templates", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._instance_templates_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._instance_templates_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._instance_templates_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._instance_templates_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("instance-templates".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("instances", Some(opt)) => { + match opt.subcommand() { + ("add-access-config", Some(opt)) => { + call_result = self._instances_add_access_config(opt, dry_run, &mut err); + }, + ("aggregated-list", Some(opt)) => { + call_result = self._instances_aggregated_list(opt, dry_run, &mut err); + }, + ("attach-disk", Some(opt)) => { + call_result = self._instances_attach_disk(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._instances_delete(opt, dry_run, &mut err); + }, + ("delete-access-config", Some(opt)) => { + call_result = self._instances_delete_access_config(opt, dry_run, &mut err); + }, + ("detach-disk", Some(opt)) => { + call_result = self._instances_detach_disk(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._instances_get(opt, dry_run, &mut err); + }, + ("get-serial-port-output", Some(opt)) => { + call_result = self._instances_get_serial_port_output(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._instances_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._instances_list(opt, dry_run, &mut err); + }, + ("reset", Some(opt)) => { + call_result = self._instances_reset(opt, dry_run, &mut err); + }, + ("set-disk-auto-delete", Some(opt)) => { + call_result = self._instances_set_disk_auto_delete(opt, dry_run, &mut err); + }, + ("set-metadata", Some(opt)) => { + call_result = self._instances_set_metadata(opt, dry_run, &mut err); + }, + ("set-scheduling", Some(opt)) => { + call_result = self._instances_set_scheduling(opt, dry_run, &mut err); + }, + ("set-tags", Some(opt)) => { + call_result = self._instances_set_tags(opt, dry_run, &mut err); + }, + ("start", Some(opt)) => { + call_result = self._instances_start(opt, dry_run, &mut err); + }, + ("stop", Some(opt)) => { + call_result = self._instances_stop(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("instances".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("licenses", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._licenses_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("licenses".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("machine-types", Some(opt)) => { + match opt.subcommand() { + ("aggregated-list", Some(opt)) => { + call_result = self._machine_types_aggregated_list(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._machine_types_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._machine_types_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("machine-types".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("networks", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._networks_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._networks_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._networks_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._networks_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("networks".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("projects", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._projects_get(opt, dry_run, &mut err); + }, + ("move-disk", Some(opt)) => { + call_result = self._projects_move_disk(opt, dry_run, &mut err); + }, + ("move-instance", Some(opt)) => { + call_result = self._projects_move_instance(opt, dry_run, &mut err); + }, + ("set-common-instance-metadata", Some(opt)) => { + call_result = self._projects_set_common_instance_metadata(opt, dry_run, &mut err); + }, + ("set-usage-export-bucket", Some(opt)) => { + call_result = self._projects_set_usage_export_bucket(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("projects".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("region-operations", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._region_operations_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._region_operations_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._region_operations_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("region-operations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("regions", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._regions_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._regions_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("regions".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("routes", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._routes_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._routes_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._routes_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._routes_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("routes".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("snapshots", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._snapshots_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._snapshots_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._snapshots_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("snapshots".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("target-http-proxies", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._target_http_proxies_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._target_http_proxies_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._target_http_proxies_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._target_http_proxies_list(opt, dry_run, &mut err); + }, + ("set-url-map", Some(opt)) => { + call_result = self._target_http_proxies_set_url_map(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("target-http-proxies".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("target-instances", Some(opt)) => { + match opt.subcommand() { + ("aggregated-list", Some(opt)) => { + call_result = self._target_instances_aggregated_list(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._target_instances_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._target_instances_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._target_instances_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._target_instances_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("target-instances".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("target-pools", Some(opt)) => { + match opt.subcommand() { + ("add-health-check", Some(opt)) => { + call_result = self._target_pools_add_health_check(opt, dry_run, &mut err); + }, + ("add-instance", Some(opt)) => { + call_result = self._target_pools_add_instance(opt, dry_run, &mut err); + }, + ("aggregated-list", Some(opt)) => { + call_result = self._target_pools_aggregated_list(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._target_pools_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._target_pools_get(opt, dry_run, &mut err); + }, + ("get-health", Some(opt)) => { + call_result = self._target_pools_get_health(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._target_pools_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._target_pools_list(opt, dry_run, &mut err); + }, + ("remove-health-check", Some(opt)) => { + call_result = self._target_pools_remove_health_check(opt, dry_run, &mut err); + }, + ("remove-instance", Some(opt)) => { + call_result = self._target_pools_remove_instance(opt, dry_run, &mut err); + }, + ("set-backup", Some(opt)) => { + call_result = self._target_pools_set_backup(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("target-pools".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("target-vpn-gateways", Some(opt)) => { + match opt.subcommand() { + ("aggregated-list", Some(opt)) => { + call_result = self._target_vpn_gateways_aggregated_list(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._target_vpn_gateways_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._target_vpn_gateways_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._target_vpn_gateways_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._target_vpn_gateways_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("target-vpn-gateways".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("url-maps", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._url_maps_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._url_maps_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._url_maps_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._url_maps_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._url_maps_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._url_maps_update(opt, dry_run, &mut err); + }, + ("validate", Some(opt)) => { + call_result = self._url_maps_validate(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("url-maps".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("vpn-tunnels", Some(opt)) => { + match opt.subcommand() { + ("aggregated-list", Some(opt)) => { + call_result = self._vpn_tunnels_aggregated_list(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._vpn_tunnels_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._vpn_tunnels_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._vpn_tunnels_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._vpn_tunnels_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("vpn-tunnels".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("zone-operations", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._zone_operations_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._zone_operations_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._zone_operations_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("zone-operations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("zones", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._zones_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._zones_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("zones".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_backend_services { - if self.opt.cmd_delete { - call_result = self._backend_services_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._backend_services_get(dry_run, &mut err); - } else if self.opt.cmd_get_health { - call_result = self._backend_services_get_health(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._backend_services_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._backend_services_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._backend_services_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._backend_services_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_disk_types { - if self.opt.cmd_aggregated_list { - call_result = self._disk_types_aggregated_list(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._disk_types_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._disk_types_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_disks { - if self.opt.cmd_aggregated_list { - call_result = self._disks_aggregated_list(dry_run, &mut err); - } else if self.opt.cmd_create_snapshot { - call_result = self._disks_create_snapshot(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._disks_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._disks_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._disks_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._disks_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_firewalls { - if self.opt.cmd_delete { - call_result = self._firewalls_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._firewalls_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._firewalls_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._firewalls_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._firewalls_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._firewalls_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_forwarding_rules { - if self.opt.cmd_aggregated_list { - call_result = self._forwarding_rules_aggregated_list(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._forwarding_rules_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._forwarding_rules_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._forwarding_rules_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._forwarding_rules_list(dry_run, &mut err); - } else if self.opt.cmd_set_target { - call_result = self._forwarding_rules_set_target(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_global_addresses { - if self.opt.cmd_delete { - call_result = self._global_addresses_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._global_addresses_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._global_addresses_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._global_addresses_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_global_forwarding_rules { - if self.opt.cmd_delete { - call_result = self._global_forwarding_rules_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._global_forwarding_rules_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._global_forwarding_rules_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._global_forwarding_rules_list(dry_run, &mut err); - } else if self.opt.cmd_set_target { - call_result = self._global_forwarding_rules_set_target(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_global_operations { - if self.opt.cmd_aggregated_list { - call_result = self._global_operations_aggregated_list(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._global_operations_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._global_operations_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._global_operations_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_http_health_checks { - if self.opt.cmd_delete { - call_result = self._http_health_checks_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._http_health_checks_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._http_health_checks_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._http_health_checks_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._http_health_checks_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._http_health_checks_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_images { - if self.opt.cmd_delete { - call_result = self._images_delete(dry_run, &mut err); - } else if self.opt.cmd_deprecate { - call_result = self._images_deprecate(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._images_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._images_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._images_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_instance_templates { - if self.opt.cmd_delete { - call_result = self._instance_templates_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._instance_templates_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._instance_templates_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._instance_templates_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_instances { - if self.opt.cmd_add_access_config { - call_result = self._instances_add_access_config(dry_run, &mut err); - } else if self.opt.cmd_aggregated_list { - call_result = self._instances_aggregated_list(dry_run, &mut err); - } else if self.opt.cmd_attach_disk { - call_result = self._instances_attach_disk(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._instances_delete(dry_run, &mut err); - } else if self.opt.cmd_delete_access_config { - call_result = self._instances_delete_access_config(dry_run, &mut err); - } else if self.opt.cmd_detach_disk { - call_result = self._instances_detach_disk(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._instances_get(dry_run, &mut err); - } else if self.opt.cmd_get_serial_port_output { - call_result = self._instances_get_serial_port_output(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._instances_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._instances_list(dry_run, &mut err); - } else if self.opt.cmd_reset { - call_result = self._instances_reset(dry_run, &mut err); - } else if self.opt.cmd_set_disk_auto_delete { - call_result = self._instances_set_disk_auto_delete(dry_run, &mut err); - } else if self.opt.cmd_set_metadata { - call_result = self._instances_set_metadata(dry_run, &mut err); - } else if self.opt.cmd_set_scheduling { - call_result = self._instances_set_scheduling(dry_run, &mut err); - } else if self.opt.cmd_set_tags { - call_result = self._instances_set_tags(dry_run, &mut err); - } else if self.opt.cmd_start { - call_result = self._instances_start(dry_run, &mut err); - } else if self.opt.cmd_stop { - call_result = self._instances_stop(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_licenses { - if self.opt.cmd_get { - call_result = self._licenses_get(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_machine_types { - if self.opt.cmd_aggregated_list { - call_result = self._machine_types_aggregated_list(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._machine_types_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._machine_types_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_networks { - if self.opt.cmd_delete { - call_result = self._networks_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._networks_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._networks_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._networks_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_projects { - if self.opt.cmd_get { - call_result = self._projects_get(dry_run, &mut err); - } else if self.opt.cmd_move_disk { - call_result = self._projects_move_disk(dry_run, &mut err); - } else if self.opt.cmd_move_instance { - call_result = self._projects_move_instance(dry_run, &mut err); - } else if self.opt.cmd_set_common_instance_metadata { - call_result = self._projects_set_common_instance_metadata(dry_run, &mut err); - } else if self.opt.cmd_set_usage_export_bucket { - call_result = self._projects_set_usage_export_bucket(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_region_operations { - if self.opt.cmd_delete { - call_result = self._region_operations_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._region_operations_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._region_operations_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_regions { - if self.opt.cmd_get { - call_result = self._regions_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._regions_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_routes { - if self.opt.cmd_delete { - call_result = self._routes_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._routes_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._routes_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._routes_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_snapshots { - if self.opt.cmd_delete { - call_result = self._snapshots_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._snapshots_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._snapshots_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_target_http_proxies { - if self.opt.cmd_delete { - call_result = self._target_http_proxies_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._target_http_proxies_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._target_http_proxies_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._target_http_proxies_list(dry_run, &mut err); - } else if self.opt.cmd_set_url_map { - call_result = self._target_http_proxies_set_url_map(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_target_instances { - if self.opt.cmd_aggregated_list { - call_result = self._target_instances_aggregated_list(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._target_instances_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._target_instances_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._target_instances_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._target_instances_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_target_pools { - if self.opt.cmd_add_health_check { - call_result = self._target_pools_add_health_check(dry_run, &mut err); - } else if self.opt.cmd_add_instance { - call_result = self._target_pools_add_instance(dry_run, &mut err); - } else if self.opt.cmd_aggregated_list { - call_result = self._target_pools_aggregated_list(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._target_pools_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._target_pools_get(dry_run, &mut err); - } else if self.opt.cmd_get_health { - call_result = self._target_pools_get_health(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._target_pools_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._target_pools_list(dry_run, &mut err); - } else if self.opt.cmd_remove_health_check { - call_result = self._target_pools_remove_health_check(dry_run, &mut err); - } else if self.opt.cmd_remove_instance { - call_result = self._target_pools_remove_instance(dry_run, &mut err); - } else if self.opt.cmd_set_backup { - call_result = self._target_pools_set_backup(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_target_vpn_gateways { - if self.opt.cmd_aggregated_list { - call_result = self._target_vpn_gateways_aggregated_list(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._target_vpn_gateways_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._target_vpn_gateways_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._target_vpn_gateways_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._target_vpn_gateways_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_url_maps { - if self.opt.cmd_delete { - call_result = self._url_maps_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._url_maps_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._url_maps_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._url_maps_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._url_maps_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._url_maps_update(dry_run, &mut err); - } else if self.opt.cmd_validate { - call_result = self._url_maps_validate(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_vpn_tunnels { - if self.opt.cmd_aggregated_list { - call_result = self._vpn_tunnels_aggregated_list(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._vpn_tunnels_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._vpn_tunnels_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._vpn_tunnels_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._vpn_tunnels_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_zone_operations { - if self.opt.cmd_delete { - call_result = self._zone_operations_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._zone_operations_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._zone_operations_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_zones { - if self.opt.cmd_get { - call_result = self._zones_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._zones_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -10219,7 +10916,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -10232,7 +10929,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -10242,37 +10939,4612 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Compute::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("addresses", "methods: 'aggregated-list', 'delete', 'get', 'insert' and 'list'", vec![ + ("aggregated-list", + Some(r##"Retrieves the list of addresses grouped by scope."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/addresses_aggregated-list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes the specified address resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/addresses_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"The name of the region for this request."##), + Some(true), + Some(false)), + + (Some(r##"address"##), + None, + Some(r##"Name of the address resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified address resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/addresses_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"The name of the region for this request."##), + Some(true), + Some(false)), + + (Some(r##"address"##), + None, + Some(r##"Name of the address resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates an address resource in the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/addresses_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"The name of the region for this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of address resources contained within the specified region."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/addresses_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"The name of the region for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("backend-services", "methods: 'delete', 'get', 'get-health', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes the specified BackendService resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/backend-services_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"backend-service"##), + None, + Some(r##"Name of the BackendService resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified BackendService resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/backend-services_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"backend-service"##), + None, + Some(r##"Name of the BackendService resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-health", + Some(r##"Gets the most recent health check results for this BackendService."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/backend-services_get-health", + vec![ + (Some(r##"project"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"backend-service"##), + None, + Some(r##"Name of the BackendService resource to which the queried instance belongs."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a BackendService resource in the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/backend-services_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of BackendService resources available to the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/backend-services_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update the entire content of the BackendService resource. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/backend-services_patch", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"backend-service"##), + None, + Some(r##"Name of the BackendService resource to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update the entire content of the BackendService resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/backend-services_update", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"backend-service"##), + None, + Some(r##"Name of the BackendService resource to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("disk-types", "methods: 'aggregated-list', 'get' and 'list'", vec![ + ("aggregated-list", + Some(r##"Retrieves the list of disk type resources grouped by scope."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/disk-types_aggregated-list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified disk type resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/disk-types_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"disk-type"##), + None, + Some(r##"Name of the disk type resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of disk type resources available to the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/disk-types_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("disks", "methods: 'aggregated-list', 'create-snapshot', 'delete', 'get', 'insert' and 'list'", vec![ + ("aggregated-list", + Some(r##"Retrieves the list of disks grouped by scope."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/disks_aggregated-list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("create-snapshot", + Some(r##"Creates a snapshot of this disk."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/disks_create-snapshot", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"disk"##), + None, + Some(r##"Name of the persistent disk to snapshot."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes the specified persistent disk."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/disks_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"disk"##), + None, + Some(r##"Name of the persistent disk to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns a specified persistent disk."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/disks_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"disk"##), + None, + Some(r##"Name of the persistent disk to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a persistent disk in the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/disks_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of persistent disks contained within the specified zone."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/disks_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("firewalls", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes the specified firewall resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/firewalls_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"firewall"##), + None, + Some(r##"Name of the firewall resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified firewall resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/firewalls_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"firewall"##), + None, + Some(r##"Name of the firewall resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a firewall resource in the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/firewalls_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of firewall resources available to the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/firewalls_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates the specified firewall resource with the data included in the request. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/firewalls_patch", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"firewall"##), + None, + Some(r##"Name of the firewall resource to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates the specified firewall resource with the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/firewalls_update", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"firewall"##), + None, + Some(r##"Name of the firewall resource to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("forwarding-rules", "methods: 'aggregated-list', 'delete', 'get', 'insert', 'list' and 'set-target'", vec![ + ("aggregated-list", + Some(r##"Retrieves the list of forwarding rules grouped by scope."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/forwarding-rules_aggregated-list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes the specified ForwardingRule resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/forwarding-rules_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"forwarding-rule"##), + None, + Some(r##"Name of the ForwardingRule resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified ForwardingRule resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/forwarding-rules_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"forwarding-rule"##), + None, + Some(r##"Name of the ForwardingRule resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a ForwardingRule resource in the specified project and region using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/forwarding-rules_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of ForwardingRule resources available to the specified project and region."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/forwarding-rules_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-target", + Some(r##"Changes target url for forwarding rule."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/forwarding-rules_set-target", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"forwarding-rule"##), + None, + Some(r##"Name of the ForwardingRule resource in which target is to be set."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("global-addresses", "methods: 'delete', 'get', 'insert' and 'list'", vec![ + ("delete", + Some(r##"Deletes the specified address resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/global-addresses_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"address"##), + None, + Some(r##"Name of the address resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified address resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/global-addresses_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"address"##), + None, + Some(r##"Name of the address resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates an address resource in the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/global-addresses_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of global address resources."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/global-addresses_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("global-forwarding-rules", "methods: 'delete', 'get', 'insert', 'list' and 'set-target'", vec![ + ("delete", + Some(r##"Deletes the specified ForwardingRule resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/global-forwarding-rules_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"forwarding-rule"##), + None, + Some(r##"Name of the ForwardingRule resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified ForwardingRule resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/global-forwarding-rules_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"forwarding-rule"##), + None, + Some(r##"Name of the ForwardingRule resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a ForwardingRule resource in the specified project and region using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/global-forwarding-rules_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of ForwardingRule resources available to the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/global-forwarding-rules_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-target", + Some(r##"Changes target url for forwarding rule."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/global-forwarding-rules_set-target", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"forwarding-rule"##), + None, + Some(r##"Name of the ForwardingRule resource in which target is to be set."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("global-operations", "methods: 'aggregated-list', 'delete', 'get' and 'list'", vec![ + ("aggregated-list", + Some(r##"Retrieves the list of all operations grouped by scope."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/global-operations_aggregated-list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes the specified operation resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/global-operations_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"operation"##), + None, + Some(r##"Name of the operation resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves the specified operation resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/global-operations_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"operation"##), + None, + Some(r##"Name of the operation resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of operation resources contained within the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/global-operations_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("http-health-checks", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes the specified HttpHealthCheck resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/http-health-checks_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"http-health-check"##), + None, + Some(r##"Name of the HttpHealthCheck resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified HttpHealthCheck resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/http-health-checks_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"http-health-check"##), + None, + Some(r##"Name of the HttpHealthCheck resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a HttpHealthCheck resource in the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/http-health-checks_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of HttpHealthCheck resources available to the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/http-health-checks_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a HttpHealthCheck resource in the specified project using the data included in the request. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/http-health-checks_patch", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"http-health-check"##), + None, + Some(r##"Name of the HttpHealthCheck resource to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a HttpHealthCheck resource in the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/http-health-checks_update", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"http-health-check"##), + None, + Some(r##"Name of the HttpHealthCheck resource to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("images", "methods: 'delete', 'deprecate', 'get', 'insert' and 'list'", vec![ + ("delete", + Some(r##"Deletes the specified image resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/images_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"image"##), + None, + Some(r##"Name of the image resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("deprecate", + Some(r##"Sets the deprecation status of an image. + + If an empty request body is given, clears the deprecation status instead."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/images_deprecate", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"image"##), + None, + Some(r##"Image name."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified image resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/images_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"image"##), + None, + Some(r##"Name of the image resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates an image resource in the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/images_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of image resources available to the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/images_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("instance-templates", "methods: 'delete', 'get', 'insert' and 'list'", vec![ + ("delete", + Some(r##"Deletes the specified instance template resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instance-templates_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"instance-template"##), + None, + Some(r##"Name of the instance template resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified instance template resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instance-templates_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"instance-template"##), + None, + Some(r##"Name of the instance template resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates an instance template resource in the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instance-templates_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of instance template resources contained within the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instance-templates_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("instances", "methods: 'add-access-config', 'aggregated-list', 'attach-disk', 'delete', 'delete-access-config', 'detach-disk', 'get', 'get-serial-port-output', 'insert', 'list', 'reset', 'set-disk-auto-delete', 'set-metadata', 'set-scheduling', 'set-tags', 'start' and 'stop'", vec![ + ("add-access-config", + Some(r##"Adds an access config to an instance's network interface."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_add-access-config", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"The instance name for this request."##), + Some(true), + Some(false)), + + (Some(r##"network-interface"##), + None, + Some(r##"The name of the network interface to add to this instance."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("aggregated-list", + None, + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_aggregated-list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("attach-disk", + Some(r##"Attaches a Disk resource to an instance."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_attach-disk", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Instance name."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes the specified Instance resource. For more information, see Shutting down an instance."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Name of the instance resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete-access-config", + Some(r##"Deletes an access config from an instance's network interface."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_delete-access-config", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"The instance name for this request."##), + Some(true), + Some(false)), + + (Some(r##"access-config"##), + None, + Some(r##"The name of the access config to delete."##), + Some(true), + Some(false)), + + (Some(r##"network-interface"##), + None, + Some(r##"The name of the network interface."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("detach-disk", + Some(r##"Detaches a disk from an instance."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_detach-disk", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Instance name."##), + Some(true), + Some(false)), + + (Some(r##"device-name"##), + None, + Some(r##"Disk device name to detach."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified instance resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the The name of the zone for this request.."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Name of the instance resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-serial-port-output", + Some(r##"Returns the specified instance's serial port output."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_get-serial-port-output", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Name of the instance scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates an instance resource in the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of instance resources contained within the specified zone."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reset", + Some(r##"Performs a hard reset on the instance."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_reset", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Name of the instance scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-disk-auto-delete", + Some(r##"Sets the auto-delete flag for a disk attached to an instance."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_set-disk-auto-delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"The instance name."##), + Some(true), + Some(false)), + + (Some(r##"auto-delete"##), + None, + Some(r##"Whether to auto-delete the disk when the instance is deleted."##), + Some(true), + Some(false)), + + (Some(r##"device-name"##), + None, + Some(r##"The device name of the disk to modify."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-metadata", + Some(r##"Sets metadata for the specified instance to the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_set-metadata", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Name of the instance scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-scheduling", + Some(r##"Sets an instance's scheduling options."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_set-scheduling", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Instance name."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-tags", + Some(r##"Sets tags for the specified instance to the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_set-tags", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Name of the instance scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("start", + Some(r##"This method starts an instance that was stopped using the using the instances().stop method. For more information, see Restart an instance."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_start", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Name of the instance resource to start."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("stop", + Some(r##"This method stops a running instance, shutting it down cleanly, and allows you to restart the instance at a later time. Stopped instances do not incur per-minute, virtual machine usage charges while they are stopped, but any resources that the virtual machine is using, such as persistent disks and static IP addresses,will continue to be charged until they are deleted. For more information, see Stopping an instance."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/instances_stop", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Name of the instance resource to start."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("licenses", "methods: 'get'", vec![ + ("get", + Some(r##"Returns the specified license resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/licenses_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"license"##), + None, + Some(r##"Name of the license resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("machine-types", "methods: 'aggregated-list', 'get' and 'list'", vec![ + ("aggregated-list", + Some(r##"Retrieves the list of machine type resources grouped by scope."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/machine-types_aggregated-list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified machine type resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/machine-types_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"machine-type"##), + None, + Some(r##"Name of the machine type resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of machine type resources available to the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/machine-types_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("networks", "methods: 'delete', 'get', 'insert' and 'list'", vec![ + ("delete", + Some(r##"Deletes the specified network resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/networks_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"network"##), + None, + Some(r##"Name of the network resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified network resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/networks_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"network"##), + None, + Some(r##"Name of the network resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a network resource in the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/networks_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of network resources available to the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/networks_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("projects", "methods: 'get', 'move-disk', 'move-instance', 'set-common-instance-metadata' and 'set-usage-export-bucket'", vec![ + ("get", + Some(r##"Returns the specified project resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/projects_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("move-disk", + Some(r##"Moves a persistent disk from one zone to another."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/projects_move-disk", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("move-instance", + Some(r##"Moves an instance and its attached persistent disks from one zone to another."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/projects_move-instance", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-common-instance-metadata", + Some(r##"Sets metadata common to all instances within the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/projects_set-common-instance-metadata", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-usage-export-bucket", + Some(r##"Enables the usage export feature and sets the usage export bucket where reports are stored. If you provide an empty request body using this method, the usage export feature will be disabled."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/projects_set-usage-export-bucket", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("region-operations", "methods: 'delete', 'get' and 'list'", vec![ + ("delete", + Some(r##"Deletes the specified region-specific operation resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/region-operations_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"operation"##), + None, + Some(r##"Name of the operation resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves the specified region-specific operation resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/region-operations_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the zone scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"operation"##), + None, + Some(r##"Name of the operation resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of operation resources contained within the specified region."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/region-operations_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("regions", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Returns the specified region resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/regions_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of region resources available to the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/regions_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("routes", "methods: 'delete', 'get', 'insert' and 'list'", vec![ + ("delete", + Some(r##"Deletes the specified route resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/routes_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"route"##), + None, + Some(r##"Name of the route resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified route resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/routes_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"route"##), + None, + Some(r##"Name of the route resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a route resource in the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/routes_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of route resources available to the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/routes_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("snapshots", "methods: 'delete', 'get' and 'list'", vec![ + ("delete", + Some(r##"Deletes the specified persistent disk snapshot resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/snapshots_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"snapshot"##), + None, + Some(r##"Name of the persistent disk snapshot resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified persistent disk snapshot resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/snapshots_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"snapshot"##), + None, + Some(r##"Name of the persistent disk snapshot resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of persistent disk snapshot resources contained within the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/snapshots_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("target-http-proxies", "methods: 'delete', 'get', 'insert', 'list' and 'set-url-map'", vec![ + ("delete", + Some(r##"Deletes the specified TargetHttpProxy resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-http-proxies_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"target-http-proxy"##), + None, + Some(r##"Name of the TargetHttpProxy resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified TargetHttpProxy resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-http-proxies_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"target-http-proxy"##), + None, + Some(r##"Name of the TargetHttpProxy resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a TargetHttpProxy resource in the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-http-proxies_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of TargetHttpProxy resources available to the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-http-proxies_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-url-map", + Some(r##"Changes the URL map for TargetHttpProxy."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-http-proxies_set-url-map", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"target-http-proxy"##), + None, + Some(r##"Name of the TargetHttpProxy resource whose URL map is to be set."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("target-instances", "methods: 'aggregated-list', 'delete', 'get', 'insert' and 'list'", vec![ + ("aggregated-list", + Some(r##"Retrieves the list of target instances grouped by scope."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-instances_aggregated-list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes the specified TargetInstance resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-instances_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Name of the zone scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"target-instance"##), + None, + Some(r##"Name of the TargetInstance resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified TargetInstance resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-instances_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Name of the zone scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"target-instance"##), + None, + Some(r##"Name of the TargetInstance resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a TargetInstance resource in the specified project and zone using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-instances_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Name of the zone scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of TargetInstance resources available to the specified project and zone."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-instances_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Name of the zone scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("target-pools", "methods: 'add-health-check', 'add-instance', 'aggregated-list', 'delete', 'get', 'get-health', 'insert', 'list', 'remove-health-check', 'remove-instance' and 'set-backup'", vec![ + ("add-health-check", + Some(r##"Adds health check URL to targetPool."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-pools_add-health-check", + vec![ + (Some(r##"project"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"target-pool"##), + None, + Some(r##"Name of the TargetPool resource to which health_check_url is to be added."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("add-instance", + Some(r##"Adds instance url to targetPool."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-pools_add-instance", + vec![ + (Some(r##"project"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"target-pool"##), + None, + Some(r##"Name of the TargetPool resource to which instance_url is to be added."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("aggregated-list", + Some(r##"Retrieves the list of target pools grouped by scope."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-pools_aggregated-list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes the specified TargetPool resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-pools_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"target-pool"##), + None, + Some(r##"Name of the TargetPool resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified TargetPool resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-pools_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"target-pool"##), + None, + Some(r##"Name of the TargetPool resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-health", + Some(r##"Gets the most recent health check results for each IP for the given instance that is referenced by given TargetPool."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-pools_get-health", + vec![ + (Some(r##"project"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"target-pool"##), + None, + Some(r##"Name of the TargetPool resource to which the queried instance belongs."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a TargetPool resource in the specified project and region using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-pools_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of TargetPool resources available to the specified project and region."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-pools_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("remove-health-check", + Some(r##"Removes health check URL from targetPool."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-pools_remove-health-check", + vec![ + (Some(r##"project"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"target-pool"##), + None, + Some(r##"Name of the TargetPool resource to which health_check_url is to be removed."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("remove-instance", + Some(r##"Removes instance URL from targetPool."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-pools_remove-instance", + vec![ + (Some(r##"project"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"target-pool"##), + None, + Some(r##"Name of the TargetPool resource to which instance_url is to be removed."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-backup", + Some(r##"Changes backup pool configurations."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-pools_set-backup", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"Name of the region scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"target-pool"##), + None, + Some(r##"Name of the TargetPool resource for which the backup is to be set."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("target-vpn-gateways", "methods: 'aggregated-list', 'delete', 'get', 'insert' and 'list'", vec![ + ("aggregated-list", + Some(r##"Retrieves the list of target VPN gateways grouped by scope."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-vpn-gateways_aggregated-list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes the specified TargetVpnGateway resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-vpn-gateways_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"The name of the region for this request."##), + Some(true), + Some(false)), + + (Some(r##"target-vpn-gateway"##), + None, + Some(r##"Name of the TargetVpnGateway resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified TargetVpnGateway resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-vpn-gateways_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"The name of the region for this request."##), + Some(true), + Some(false)), + + (Some(r##"target-vpn-gateway"##), + None, + Some(r##"Name of the TargetVpnGateway resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a TargetVpnGateway resource in the specified project and region using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-vpn-gateways_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"The name of the region for this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of TargetVpnGateway resources available to the specified project and region."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/target-vpn-gateways_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"The name of the region for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("url-maps", "methods: 'delete', 'get', 'insert', 'list', 'patch', 'update' and 'validate'", vec![ + ("delete", + Some(r##"Deletes the specified UrlMap resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/url-maps_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"url-map"##), + None, + Some(r##"Name of the UrlMap resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified UrlMap resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/url-maps_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"url-map"##), + None, + Some(r##"Name of the UrlMap resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a UrlMap resource in the specified project using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/url-maps_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of UrlMap resources available to the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/url-maps_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update the entire content of the UrlMap resource. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/url-maps_patch", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"url-map"##), + None, + Some(r##"Name of the UrlMap resource to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update the entire content of the UrlMap resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/url-maps_update", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"url-map"##), + None, + Some(r##"Name of the UrlMap resource to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("validate", + Some(r##"Run static validation for the UrlMap. In particular, the tests of the provided UrlMap will be run. Calling this method does NOT create the UrlMap."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/url-maps_validate", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"url-map"##), + None, + Some(r##"Name of the UrlMap resource to be validated as."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("vpn-tunnels", "methods: 'aggregated-list', 'delete', 'get', 'insert' and 'list'", vec![ + ("aggregated-list", + Some(r##"Retrieves the list of VPN tunnels grouped by scope."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/vpn-tunnels_aggregated-list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes the specified VpnTunnel resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/vpn-tunnels_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"The name of the region for this request."##), + Some(true), + Some(false)), + + (Some(r##"vpn-tunnel"##), + None, + Some(r##"Name of the VpnTunnel resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified VpnTunnel resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/vpn-tunnels_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"The name of the region for this request."##), + Some(true), + Some(false)), + + (Some(r##"vpn-tunnel"##), + None, + Some(r##"Name of the VpnTunnel resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a VpnTunnel resource in the specified project and region using the data included in the request."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/vpn-tunnels_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"The name of the region for this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of VpnTunnel resources contained in the specified project and region."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/vpn-tunnels_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + Some(r##"The name of the region for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("zone-operations", "methods: 'delete', 'get' and 'list'", vec![ + ("delete", + Some(r##"Deletes the specified zone-specific operation resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/zone-operations_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Name of the zone scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"operation"##), + None, + Some(r##"Name of the operation resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves the specified zone-specific operation resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/zone-operations_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Name of the zone scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"operation"##), + None, + Some(r##"Name of the operation resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of operation resources contained within the specified zone."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/zone-operations_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Name of the zone scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("zones", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Returns the specified zone resource."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/zones_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Name of the zone resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of zone resources available to the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_compute1_cli/zones_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("compute1") + .author("Sebastian Thiel ") + .version("0.2.0+20150326") + .about("API for the Google Compute Engine service.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_compute1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/compute1/Cargo.toml b/gen/compute1/Cargo.toml index 5e8f000051..e25cf64782 100644 --- a/gen/compute1/Cargo.toml +++ b/gen/compute1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-compute1" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel "] description = "A complete library to interact with compute (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/compute1" @@ -15,9 +15,10 @@ keywords = ["compute", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/compute1/README.md b/gen/compute1/README.md index 35b68170a3..8cb6be83c5 100644 --- a/gen/compute1/README.md +++ b/gen/compute1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-compute1` library allows access to all features of the *Google compute* service. -This documentation was generated from *compute* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *compute:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *compute* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *compute:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *compute* *v1* API can be found at the [official documentation site](https://developers.google.com/compute/docs/reference/latest/). @@ -287,7 +287,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_compute1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_compute1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/compute1/src/cmn.rs b/gen/compute1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/compute1/src/cmn.rs +++ b/gen/compute1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/compute1/src/lib.rs b/gen/compute1/src/lib.rs index d903aaf7e5..2bf724e002 100644 --- a/gen/compute1/src/lib.rs +++ b/gen/compute1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *compute* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *compute:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *compute* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *compute:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *compute* *v1* API can be found at the //! [official documentation site](https://developers.google.com/compute/docs/reference/latest/). @@ -288,7 +288,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -297,7 +297,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -313,6 +312,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -449,7 +449,7 @@ impl<'a, C, A> Compute Compute { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -542,7 +542,7 @@ impl<'a, C, A> Compute } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -8740,7 +8740,7 @@ impl<'a, C, A> DiskDeleteCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8762,7 +8762,7 @@ impl<'a, C, A> DiskDeleteCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9014,7 +9014,7 @@ impl<'a, C, A> DiskAggregatedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9036,7 +9036,7 @@ impl<'a, C, A> DiskAggregatedListCall<'a, C, A> where C: BorrowMut DiskListCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9313,7 +9313,7 @@ impl<'a, C, A> DiskListCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9516,6 +9516,7 @@ impl<'a, C, A> DiskInsertCall<'a, C, A> where C: BorrowMut, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9575,11 +9576,20 @@ impl<'a, C, A> DiskInsertCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9602,7 +9612,7 @@ impl<'a, C, A> DiskInsertCall<'a, C, A> where C: BorrowMut, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9802,6 +9812,7 @@ impl<'a, C, A> DiskCreateSnapshotCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9859,11 +9870,20 @@ impl<'a, C, A> DiskCreateSnapshotCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9886,7 +9906,7 @@ impl<'a, C, A> DiskCreateSnapshotCall<'a, C, A> where C: BorrowMut DiskGetCall<'a, C, A> where C: BorrowMut, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10161,7 +10181,7 @@ impl<'a, C, A> DiskGetCall<'a, C, A> where C: BorrowMut, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10415,7 +10435,7 @@ impl<'a, C, A> AddresseListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10437,7 +10457,7 @@ impl<'a, C, A> AddresseListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10700,7 +10720,7 @@ impl<'a, C, A> AddresseAggregatedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10722,7 +10742,7 @@ impl<'a, C, A> AddresseAggregatedListCall<'a, C, A> where C: BorrowMut AddresseGetCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10986,7 +11006,7 @@ impl<'a, C, A> AddresseGetCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11176,6 +11196,7 @@ impl<'a, C, A> AddresseInsertCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11232,11 +11253,20 @@ impl<'a, C, A> AddresseInsertCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11259,7 +11289,7 @@ impl<'a, C, A> AddresseInsertCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11502,7 +11532,7 @@ impl<'a, C, A> AddresseDeleteCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11524,7 +11554,7 @@ impl<'a, C, A> AddresseDeleteCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11713,6 +11743,7 @@ impl<'a, C, A> UrlMapInsertCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11768,11 +11799,20 @@ impl<'a, C, A> UrlMapInsertCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11795,7 +11835,7 @@ impl<'a, C, A> UrlMapInsertCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -12026,7 +12066,7 @@ impl<'a, C, A> UrlMapGetCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12048,7 +12088,7 @@ impl<'a, C, A> UrlMapGetCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12228,6 +12268,7 @@ impl<'a, C, A> UrlMapValidateCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, UrlMapsValidateResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12284,11 +12325,20 @@ impl<'a, C, A> UrlMapValidateCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12311,7 +12361,7 @@ impl<'a, C, A> UrlMapValidateCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -12565,7 +12615,7 @@ impl<'a, C, A> UrlMapListCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12587,7 +12637,7 @@ impl<'a, C, A> UrlMapListCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12778,6 +12828,7 @@ impl<'a, C, A> UrlMapPatchCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12834,11 +12885,20 @@ impl<'a, C, A> UrlMapPatchCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12861,7 +12921,7 @@ impl<'a, C, A> UrlMapPatchCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -13053,6 +13113,7 @@ impl<'a, C, A> UrlMapUpdateCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13109,11 +13170,20 @@ impl<'a, C, A> UrlMapUpdateCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13136,7 +13206,7 @@ impl<'a, C, A> UrlMapUpdateCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -13377,7 +13447,7 @@ impl<'a, C, A> UrlMapDeleteCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13399,7 +13469,7 @@ impl<'a, C, A> UrlMapDeleteCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -13578,6 +13648,7 @@ impl<'a, C, A> GlobalAddresseInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13633,11 +13704,20 @@ impl<'a, C, A> GlobalAddresseInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13660,7 +13740,7 @@ impl<'a, C, A> GlobalAddresseInsertCall<'a, C, A> where C: BorrowMut GlobalAddresseListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13926,7 +14006,7 @@ impl<'a, C, A> GlobalAddresseListCall<'a, C, A> where C: BorrowMut GlobalAddresseGetCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14188,7 +14268,7 @@ impl<'a, C, A> GlobalAddresseGetCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -14417,7 +14497,7 @@ impl<'a, C, A> GlobalAddresseDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14439,7 +14519,7 @@ impl<'a, C, A> GlobalAddresseDeleteCall<'a, C, A> where C: BorrowMut SnapshotGetCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14690,7 +14770,7 @@ impl<'a, C, A> SnapshotGetCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -14932,7 +15012,7 @@ impl<'a, C, A> SnapshotListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14954,7 +15034,7 @@ impl<'a, C, A> SnapshotListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -15194,7 +15274,7 @@ impl<'a, C, A> SnapshotDeleteCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15216,7 +15296,7 @@ impl<'a, C, A> SnapshotDeleteCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -15447,7 +15527,7 @@ impl<'a, C, A> DiskTypeGetCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15469,7 +15549,7 @@ impl<'a, C, A> DiskTypeGetCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -15721,7 +15801,7 @@ impl<'a, C, A> DiskTypeAggregatedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15743,7 +15823,7 @@ impl<'a, C, A> DiskTypeAggregatedListCall<'a, C, A> where C: BorrowMut DiskTypeListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16020,7 +16100,7 @@ impl<'a, C, A> DiskTypeListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -16270,7 +16350,7 @@ impl<'a, C, A> ZoneGetCall<'a, C, A> where C: BorrowMut, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16292,7 +16372,7 @@ impl<'a, C, A> ZoneGetCall<'a, C, A> where C: BorrowMut, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -16534,7 +16614,7 @@ impl<'a, C, A> ZoneListCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16556,7 +16636,7 @@ impl<'a, C, A> ZoneListCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -16748,6 +16828,7 @@ impl<'a, C, A> InstanceSetSchedulingCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -16805,11 +16886,20 @@ impl<'a, C, A> InstanceSetSchedulingCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -16832,7 +16922,7 @@ impl<'a, C, A> InstanceSetSchedulingCall<'a, C, A> where C: BorrowMut InstanceDeleteCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17107,7 +17197,7 @@ impl<'a, C, A> InstanceDeleteCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -17353,7 +17443,7 @@ impl<'a, C, A> InstanceGetSerialPortOutputCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17375,7 +17465,7 @@ impl<'a, C, A> InstanceGetSerialPortOutputCall<'a, C, A> where C: BorrowMut InstanceSetDiskAutoDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17649,7 +17739,7 @@ impl<'a, C, A> InstanceSetDiskAutoDeleteCall<'a, C, A> where C: BorrowMut InstanceAddAccessConfigCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17919,11 +18010,20 @@ impl<'a, C, A> InstanceAddAccessConfigCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17946,7 +18046,7 @@ impl<'a, C, A> InstanceAddAccessConfigCall<'a, C, A> where C: BorrowMut InstanceStartCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18231,7 +18331,7 @@ impl<'a, C, A> InstanceStartCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -18472,7 +18572,7 @@ impl<'a, C, A> InstanceGetCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18494,7 +18594,7 @@ impl<'a, C, A> InstanceGetCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -18685,6 +18785,7 @@ impl<'a, C, A> InstanceSetTagCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -18742,11 +18843,20 @@ impl<'a, C, A> InstanceSetTagCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -18769,7 +18879,7 @@ impl<'a, C, A> InstanceSetTagCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -18972,6 +19082,7 @@ impl<'a, C, A> InstanceSetMetadataCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -19029,11 +19140,20 @@ impl<'a, C, A> InstanceSetMetadataCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -19056,7 +19176,7 @@ impl<'a, C, A> InstanceSetMetadataCall<'a, C, A> where C: BorrowMut InstanceDetachDiskCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19333,7 +19453,7 @@ impl<'a, C, A> InstanceDetachDiskCall<'a, C, A> where C: BorrowMut InstanceStopCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19606,7 +19726,7 @@ impl<'a, C, A> InstanceStopCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -19796,6 +19916,7 @@ impl<'a, C, A> InstanceInsertCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -19852,11 +19973,20 @@ impl<'a, C, A> InstanceInsertCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -19879,7 +20009,7 @@ impl<'a, C, A> InstanceInsertCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -20122,7 +20252,7 @@ impl<'a, C, A> InstanceResetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -20144,7 +20274,7 @@ impl<'a, C, A> InstanceResetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -20389,7 +20519,7 @@ impl<'a, C, A> InstanceDeleteAccessConfigCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -20411,7 +20541,7 @@ impl<'a, C, A> InstanceDeleteAccessConfigCall<'a, C, A> where C: BorrowMut InstanceAttachDiskCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -20679,11 +20810,20 @@ impl<'a, C, A> InstanceAttachDiskCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -20706,7 +20846,7 @@ impl<'a, C, A> InstanceAttachDiskCall<'a, C, A> where C: BorrowMut InstanceListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -20994,7 +21134,7 @@ impl<'a, C, A> InstanceListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -21255,7 +21395,7 @@ impl<'a, C, A> InstanceAggregatedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -21277,7 +21417,7 @@ impl<'a, C, A> InstanceAggregatedListCall<'a, C, A> where C: BorrowMut BackendServiceGetHealthCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, BackendServiceGroupHealth)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -21524,11 +21665,20 @@ impl<'a, C, A> BackendServiceGetHealthCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -21551,7 +21701,7 @@ impl<'a, C, A> BackendServiceGetHealthCall<'a, C, A> where C: BorrowMut BackendServiceDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -21813,7 +21963,7 @@ impl<'a, C, A> BackendServiceDeleteCall<'a, C, A> where C: BorrowMut BackendServiceGetCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -22064,7 +22214,7 @@ impl<'a, C, A> BackendServiceGetCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -22244,6 +22394,7 @@ impl<'a, C, A> BackendServiceUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -22300,11 +22451,20 @@ impl<'a, C, A> BackendServiceUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -22327,7 +22487,7 @@ impl<'a, C, A> BackendServiceUpdateCall<'a, C, A> where C: BorrowMut BackendServiceListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -22603,7 +22763,7 @@ impl<'a, C, A> BackendServiceListCall<'a, C, A> where C: BorrowMut BackendServicePatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -22850,11 +23011,20 @@ impl<'a, C, A> BackendServicePatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -22877,7 +23047,7 @@ impl<'a, C, A> BackendServicePatchCall<'a, C, A> where C: BorrowMut BackendServiceInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -23123,11 +23294,20 @@ impl<'a, C, A> BackendServiceInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -23150,7 +23330,7 @@ impl<'a, C, A> BackendServiceInsertCall<'a, C, A> where C: BorrowMut LicenseGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -23403,7 +23583,7 @@ impl<'a, C, A> LicenseGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -23582,6 +23762,7 @@ impl<'a, C, A> NetworkInsertCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -23637,11 +23818,20 @@ impl<'a, C, A> NetworkInsertCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -23664,7 +23854,7 @@ impl<'a, C, A> NetworkInsertCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -23908,7 +24098,7 @@ impl<'a, C, A> NetworkListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -23930,7 +24120,7 @@ impl<'a, C, A> NetworkListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -24170,7 +24360,7 @@ impl<'a, C, A> NetworkDeleteCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -24192,7 +24382,7 @@ impl<'a, C, A> NetworkDeleteCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -24421,7 +24611,7 @@ impl<'a, C, A> NetworkGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -24443,7 +24633,7 @@ impl<'a, C, A> NetworkGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -24685,7 +24875,7 @@ impl<'a, C, A> GlobalOperationListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -24707,7 +24897,7 @@ impl<'a, C, A> GlobalOperationListCall<'a, C, A> where C: BorrowMut GlobalOperationGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -24969,7 +25159,7 @@ impl<'a, C, A> GlobalOperationGetCall<'a, C, A> where C: BorrowMut GlobalOperationDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -25219,7 +25409,7 @@ impl<'a, C, A> GlobalOperationDeleteCall<'a, C, A> where C: BorrowMut GlobalOperationAggregatedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -25473,7 +25663,7 @@ impl<'a, C, A> GlobalOperationAggregatedListCall<'a, C, A> where C: BorrowMut RegionListCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -25748,7 +25938,7 @@ impl<'a, C, A> RegionListCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -25988,7 +26178,7 @@ impl<'a, C, A> RegionGetCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -26010,7 +26200,7 @@ impl<'a, C, A> RegionGetCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -26252,7 +26442,7 @@ impl<'a, C, A> ForwardingRuleAggregatedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -26274,7 +26464,7 @@ impl<'a, C, A> ForwardingRuleAggregatedListCall<'a, C, A> where C: BorrowMut ForwardingRuleInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -26521,11 +26712,20 @@ impl<'a, C, A> ForwardingRuleInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -26548,7 +26748,7 @@ impl<'a, C, A> ForwardingRuleInsertCall<'a, C, A> where C: BorrowMut ForwardingRuleSetTargetCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -26798,11 +26999,20 @@ impl<'a, C, A> ForwardingRuleSetTargetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -26825,7 +27035,7 @@ impl<'a, C, A> ForwardingRuleSetTargetCall<'a, C, A> where C: BorrowMut ForwardingRuleGetCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -27100,7 +27310,7 @@ impl<'a, C, A> ForwardingRuleGetCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -27354,7 +27564,7 @@ impl<'a, C, A> ForwardingRuleListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -27376,7 +27586,7 @@ impl<'a, C, A> ForwardingRuleListCall<'a, C, A> where C: BorrowMut ForwardingRuleDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -27650,7 +27860,7 @@ impl<'a, C, A> ForwardingRuleDeleteCall<'a, C, A> where C: BorrowMut TargetPoolListCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -27926,7 +28136,7 @@ impl<'a, C, A> TargetPoolListCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -28128,6 +28338,7 @@ impl<'a, C, A> TargetPoolAddHealthCheckCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -28185,11 +28396,20 @@ impl<'a, C, A> TargetPoolAddHealthCheckCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -28212,7 +28432,7 @@ impl<'a, C, A> TargetPoolAddHealthCheckCall<'a, C, A> where C: BorrowMut TargetPoolInsertCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -28469,11 +28690,20 @@ impl<'a, C, A> TargetPoolInsertCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -28496,7 +28726,7 @@ impl<'a, C, A> TargetPoolInsertCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -28689,6 +28919,7 @@ impl<'a, C, A> TargetPoolRemoveHealthCheckCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -28746,11 +28977,20 @@ impl<'a, C, A> TargetPoolRemoveHealthCheckCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -28773,7 +29013,7 @@ impl<'a, C, A> TargetPoolRemoveHealthCheckCall<'a, C, A> where C: BorrowMut TargetPoolGetHealthCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, TargetPoolInstanceHealth)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -29032,11 +29273,20 @@ impl<'a, C, A> TargetPoolGetHealthCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -29059,7 +29309,7 @@ impl<'a, C, A> TargetPoolGetHealthCall<'a, C, A> where C: BorrowMut TargetPoolSetBackupCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -29323,11 +29574,20 @@ impl<'a, C, A> TargetPoolSetBackupCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -29350,7 +29610,7 @@ impl<'a, C, A> TargetPoolSetBackupCall<'a, C, A> where C: BorrowMut TargetPoolAggregatedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -29643,7 +29903,7 @@ impl<'a, C, A> TargetPoolAggregatedListCall<'a, C, A> where C: BorrowMut TargetPoolGetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -29907,7 +30167,7 @@ impl<'a, C, A> TargetPoolGetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -30098,6 +30358,7 @@ impl<'a, C, A> TargetPoolAddInstanceCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -30155,11 +30416,20 @@ impl<'a, C, A> TargetPoolAddInstanceCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -30182,7 +30452,7 @@ impl<'a, C, A> TargetPoolAddInstanceCall<'a, C, A> where C: BorrowMut TargetPoolRemoveInstanceCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -30441,11 +30712,20 @@ impl<'a, C, A> TargetPoolRemoveInstanceCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -30468,7 +30748,7 @@ impl<'a, C, A> TargetPoolRemoveInstanceCall<'a, C, A> where C: BorrowMut TargetPoolDeleteCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -30742,7 +31022,7 @@ impl<'a, C, A> TargetPoolDeleteCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -30996,7 +31276,7 @@ impl<'a, C, A> TargetInstanceListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -31018,7 +31298,7 @@ impl<'a, C, A> TargetInstanceListCall<'a, C, A> where C: BorrowMut TargetInstanceInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -31275,11 +31556,20 @@ impl<'a, C, A> TargetInstanceInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -31302,7 +31592,7 @@ impl<'a, C, A> TargetInstanceInsertCall<'a, C, A> where C: BorrowMut TargetInstanceAggregatedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -31578,7 +31868,7 @@ impl<'a, C, A> TargetInstanceAggregatedListCall<'a, C, A> where C: BorrowMut TargetInstanceGetCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -31842,7 +32132,7 @@ impl<'a, C, A> TargetInstanceGetCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -32083,7 +32373,7 @@ impl<'a, C, A> TargetInstanceDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -32105,7 +32395,7 @@ impl<'a, C, A> TargetInstanceDeleteCall<'a, C, A> where C: BorrowMut GlobalForwardingRuleGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -32366,7 +32656,7 @@ impl<'a, C, A> GlobalForwardingRuleGetCall<'a, C, A> where C: BorrowMut GlobalForwardingRuleDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -32617,7 +32907,7 @@ impl<'a, C, A> GlobalForwardingRuleDeleteCall<'a, C, A> where C: BorrowMut GlobalForwardingRuleSetTargetCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -32853,11 +33144,20 @@ impl<'a, C, A> GlobalForwardingRuleSetTargetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -32880,7 +33180,7 @@ impl<'a, C, A> GlobalForwardingRuleSetTargetCall<'a, C, A> where C: BorrowMut GlobalForwardingRuleInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -33126,11 +33427,20 @@ impl<'a, C, A> GlobalForwardingRuleInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -33153,7 +33463,7 @@ impl<'a, C, A> GlobalForwardingRuleInsertCall<'a, C, A> where C: BorrowMut GlobalForwardingRuleListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -33419,7 +33729,7 @@ impl<'a, C, A> GlobalForwardingRuleListCall<'a, C, A> where C: BorrowMut ImageListCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -33694,7 +34004,7 @@ impl<'a, C, A> ImageListCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -33934,7 +34244,7 @@ impl<'a, C, A> ImageDeleteCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -33956,7 +34266,7 @@ impl<'a, C, A> ImageDeleteCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -34138,6 +34448,7 @@ impl<'a, C, A> ImageDeprecateCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -34194,11 +34505,20 @@ impl<'a, C, A> ImageDeprecateCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -34221,7 +34541,7 @@ impl<'a, C, A> ImageDeprecateCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -34412,6 +34732,7 @@ impl<'a, C, A> ImageInsertCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -34467,11 +34788,20 @@ impl<'a, C, A> ImageInsertCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -34494,7 +34824,7 @@ impl<'a, C, A> ImageInsertCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -34725,7 +35055,7 @@ impl<'a, C, A> ImageGetCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -34747,7 +35077,7 @@ impl<'a, C, A> ImageGetCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -34989,7 +35319,7 @@ impl<'a, C, A> MachineTypeAggregatedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -35011,7 +35341,7 @@ impl<'a, C, A> MachineTypeAggregatedListCall<'a, C, A> where C: BorrowMut MachineTypeGetCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -35275,7 +35605,7 @@ impl<'a, C, A> MachineTypeGetCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -35529,7 +35859,7 @@ impl<'a, C, A> MachineTypeListCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -35551,7 +35881,7 @@ impl<'a, C, A> MachineTypeListCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -35814,7 +36144,7 @@ impl<'a, C, A> TargetVpnGatewayAggregatedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -35836,7 +36166,7 @@ impl<'a, C, A> TargetVpnGatewayAggregatedListCall<'a, C, A> where C: BorrowMut TargetVpnGatewayGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -36100,7 +36430,7 @@ impl<'a, C, A> TargetVpnGatewayGetCall<'a, C, A> where C: BorrowMut TargetVpnGatewayListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -36376,7 +36706,7 @@ impl<'a, C, A> TargetVpnGatewayListCall<'a, C, A> where C: BorrowMut TargetVpnGatewayInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -36633,11 +36964,20 @@ impl<'a, C, A> TargetVpnGatewayInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -36660,7 +37000,7 @@ impl<'a, C, A> TargetVpnGatewayInsertCall<'a, C, A> where C: BorrowMut TargetVpnGatewayDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -36925,7 +37265,7 @@ impl<'a, C, A> TargetVpnGatewayDeleteCall<'a, C, A> where C: BorrowMut ProjectMoveDiskCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -37169,11 +37510,20 @@ impl<'a, C, A> ProjectMoveDiskCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -37196,7 +37546,7 @@ impl<'a, C, A> ProjectMoveDiskCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -37377,6 +37727,7 @@ impl<'a, C, A> ProjectSetCommonInstanceMetadataCall<'a, C, A> where C: BorrowMut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -37432,11 +37783,20 @@ impl<'a, C, A> ProjectSetCommonInstanceMetadataCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -37459,7 +37819,7 @@ impl<'a, C, A> ProjectSetCommonInstanceMetadataCall<'a, C, A> where C: BorrowMut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -37688,7 +38048,7 @@ impl<'a, C, A> ProjectGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -37710,7 +38070,7 @@ impl<'a, C, A> ProjectGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -37879,6 +38239,7 @@ impl<'a, C, A> ProjectMoveInstanceCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -37934,11 +38295,20 @@ impl<'a, C, A> ProjectMoveInstanceCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -37961,7 +38331,7 @@ impl<'a, C, A> ProjectMoveInstanceCall<'a, C, A> where C: BorrowMut ProjectSetUsageExportBucketCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -38197,11 +38568,20 @@ impl<'a, C, A> ProjectSetUsageExportBucketCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -38224,7 +38604,7 @@ impl<'a, C, A> ProjectSetUsageExportBucketCall<'a, C, A> where C: BorrowMut HttpHealthCheckGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -38477,7 +38857,7 @@ impl<'a, C, A> HttpHealthCheckGetCall<'a, C, A> where C: BorrowMut HttpHealthCheckPatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -38713,11 +39094,20 @@ impl<'a, C, A> HttpHealthCheckPatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -38740,7 +39130,7 @@ impl<'a, C, A> HttpHealthCheckPatchCall<'a, C, A> where C: BorrowMut HttpHealthCheckListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -39016,7 +39406,7 @@ impl<'a, C, A> HttpHealthCheckListCall<'a, C, A> where C: BorrowMut HttpHealthCheckDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -39278,7 +39668,7 @@ impl<'a, C, A> HttpHealthCheckDeleteCall<'a, C, A> where C: BorrowMut HttpHealthCheckInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -39512,11 +39903,20 @@ impl<'a, C, A> HttpHealthCheckInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -39539,7 +39939,7 @@ impl<'a, C, A> HttpHealthCheckInsertCall<'a, C, A> where C: BorrowMut HttpHealthCheckUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -39777,11 +40178,20 @@ impl<'a, C, A> HttpHealthCheckUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -39804,7 +40214,7 @@ impl<'a, C, A> HttpHealthCheckUpdateCall<'a, C, A> where C: BorrowMut InstanceTemplateDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -40067,7 +40477,7 @@ impl<'a, C, A> InstanceTemplateDeleteCall<'a, C, A> where C: BorrowMut InstanceTemplateGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -40318,7 +40728,7 @@ impl<'a, C, A> InstanceTemplateGetCall<'a, C, A> where C: BorrowMut InstanceTemplateListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -40582,7 +40992,7 @@ impl<'a, C, A> InstanceTemplateListCall<'a, C, A> where C: BorrowMut InstanceTemplateInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -40827,11 +41238,20 @@ impl<'a, C, A> InstanceTemplateInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -40854,7 +41274,7 @@ impl<'a, C, A> InstanceTemplateInsertCall<'a, C, A> where C: BorrowMut TargetHttpProxyDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -41107,7 +41527,7 @@ impl<'a, C, A> TargetHttpProxyDeleteCall<'a, C, A> where C: BorrowMut TargetHttpProxyListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -41371,7 +41791,7 @@ impl<'a, C, A> TargetHttpProxyListCall<'a, C, A> where C: BorrowMut TargetHttpProxyGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -41633,7 +42053,7 @@ impl<'a, C, A> TargetHttpProxyGetCall<'a, C, A> where C: BorrowMut TargetHttpProxySetUrlMapCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -41869,11 +42290,20 @@ impl<'a, C, A> TargetHttpProxySetUrlMapCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -41896,7 +42326,7 @@ impl<'a, C, A> TargetHttpProxySetUrlMapCall<'a, C, A> where C: BorrowMut TargetHttpProxyInsertCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -42142,11 +42573,20 @@ impl<'a, C, A> TargetHttpProxyInsertCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -42169,7 +42609,7 @@ impl<'a, C, A> TargetHttpProxyInsertCall<'a, C, A> where C: BorrowMut ZoneOperationDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -42423,7 +42863,7 @@ impl<'a, C, A> ZoneOperationDeleteCall<'a, C, A> where C: BorrowMut ZoneOperationListCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -42689,7 +43129,7 @@ impl<'a, C, A> ZoneOperationListCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -42941,7 +43381,7 @@ impl<'a, C, A> ZoneOperationGetCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -42963,7 +43403,7 @@ impl<'a, C, A> ZoneOperationGetCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -43202,7 +43642,7 @@ impl<'a, C, A> RouteGetCall<'a, C, A> where C: BorrowMut, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -43224,7 +43664,7 @@ impl<'a, C, A> RouteGetCall<'a, C, A> where C: BorrowMut, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -43403,6 +43843,7 @@ impl<'a, C, A> RouteInsertCall<'a, C, A> where C: BorrowMut, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -43458,11 +43899,20 @@ impl<'a, C, A> RouteInsertCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -43485,7 +43935,7 @@ impl<'a, C, A> RouteInsertCall<'a, C, A> where C: BorrowMut, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -43729,7 +44179,7 @@ impl<'a, C, A> RouteListCall<'a, C, A> where C: BorrowMut, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -43751,7 +44201,7 @@ impl<'a, C, A> RouteListCall<'a, C, A> where C: BorrowMut, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -43991,7 +44441,7 @@ impl<'a, C, A> RouteDeleteCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -44013,7 +44463,7 @@ impl<'a, C, A> RouteDeleteCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -44193,6 +44643,7 @@ impl<'a, C, A> FirewallPatchCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -44249,11 +44700,20 @@ impl<'a, C, A> FirewallPatchCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -44276,7 +44736,7 @@ impl<'a, C, A> FirewallPatchCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -44517,7 +44977,7 @@ impl<'a, C, A> FirewallGetCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -44539,7 +44999,7 @@ impl<'a, C, A> FirewallGetCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -44718,6 +45178,7 @@ impl<'a, C, A> FirewallInsertCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -44773,11 +45234,20 @@ impl<'a, C, A> FirewallInsertCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -44800,7 +45270,7 @@ impl<'a, C, A> FirewallInsertCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -44982,6 +45452,7 @@ impl<'a, C, A> FirewallUpdateCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -45038,11 +45509,20 @@ impl<'a, C, A> FirewallUpdateCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -45065,7 +45545,7 @@ impl<'a, C, A> FirewallUpdateCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -45306,7 +45786,7 @@ impl<'a, C, A> FirewallDeleteCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -45328,7 +45808,7 @@ impl<'a, C, A> FirewallDeleteCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -45570,7 +46050,7 @@ impl<'a, C, A> FirewallListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -45592,7 +46072,7 @@ impl<'a, C, A> FirewallListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -45834,7 +46314,7 @@ impl<'a, C, A> VpnTunnelDeleteCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -45856,7 +46336,7 @@ impl<'a, C, A> VpnTunnelDeleteCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -46110,7 +46590,7 @@ impl<'a, C, A> VpnTunnelListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -46132,7 +46612,7 @@ impl<'a, C, A> VpnTunnelListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -46384,7 +46864,7 @@ impl<'a, C, A> VpnTunnelGetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -46406,7 +46886,7 @@ impl<'a, C, A> VpnTunnelGetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -46596,6 +47076,7 @@ impl<'a, C, A> VpnTunnelInsertCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -46652,11 +47133,20 @@ impl<'a, C, A> VpnTunnelInsertCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -46679,7 +47169,7 @@ impl<'a, C, A> VpnTunnelInsertCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -46933,7 +47423,7 @@ impl<'a, C, A> VpnTunnelAggregatedListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -46955,7 +47445,7 @@ impl<'a, C, A> VpnTunnelAggregatedListCall<'a, C, A> where C: BorrowMut RegionOperationListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -47232,7 +47722,7 @@ impl<'a, C, A> RegionOperationListCall<'a, C, A> where C: BorrowMut RegionOperationDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -47505,7 +47995,7 @@ impl<'a, C, A> RegionOperationDeleteCall<'a, C, A> where C: BorrowMut RegionOperationGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -47758,7 +48248,7 @@ impl<'a, C, A> RegionOperationGetCall<'a, C, A> where C: BorrowMut"] description = "A complete library to interact with container (protocol v1beta1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/container1_beta1-cli" @@ -17,15 +17,14 @@ keywords = ["container", "google", "cli"] name = "container1-beta1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-container1_beta1] path = "../container1_beta1" diff --git a/gen/container1_beta1-cli/README.md b/gen/container1_beta1-cli/README.md index 9d034a5899..0c3b64a97f 100644 --- a/gen/container1_beta1-cli/README.md +++ b/gen/container1_beta1-cli/README.md @@ -10,29 +10,31 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *container* API can be found at the +[official documentation site](https://cloud.google.com/container-engine/docs/v1beta1/). + # Usage -This documentation was generated from the *container* API at revision *20150420*. The CLI is at version *0.1.0*. +This documentation was generated from the *container* API at revision *20150420*. The CLI is at version *0.2.0*. ```bash - container1-beta1 [options] projects clusters-list [-p ...] [-o ] - container1-beta1 [options] projects operations-list [-p ...] [-o ] - container1-beta1 [options] projects zones-clusters-create -r ... [-p ...] [-o ] - container1-beta1 [options] projects zones-clusters-delete [-p ...] [-o ] - container1-beta1 [options] projects zones-clusters-get [-p ...] [-o ] - container1-beta1 [options] projects zones-clusters-list [-p ...] [-o ] - container1-beta1 [options] projects zones-operations-get [-p ...] [-o ] - container1-beta1 [options] projects zones-operations-list [-p ...] [-o ] - container1-beta1 [options] projects zones-tokens-get [-p ...] [-o ] +container1-beta1 [options] + projects + clusters-list [-p ]... [-o ] + operations-list [-p ]... [-o ] + zones-clusters-create (-r )... [-p ]... [-o ] + zones-clusters-delete [-p ]... [-o ] + zones-clusters-get [-p ]... [-o ] + zones-clusters-list [-p ]... [-o ] + zones-operations-get [-p ]... [-o ] + zones-operations-list [-p ]... [-o ] + zones-tokens-get [-p ]... [-o ] container1-beta1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_container1_beta1_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/container1_beta1-cli/mkdocs.yml b/gen/container1_beta1-cli/mkdocs.yml index 3f42cb1b06..76ea978048 100644 --- a/gen/container1_beta1-cli/mkdocs.yml +++ b/gen/container1_beta1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: container v0.1.0+20150420 +site_name: container v0.2.0+20150420 site_url: http://byron.github.io/google-apis-rs/google-container1_beta1-cli site_description: Write integrating applications with bcore diff --git a/gen/container1_beta1-cli/src/cmn.rs b/gen/container1_beta1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/container1_beta1-cli/src/cmn.rs +++ b/gen/container1_beta1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/container1_beta1-cli/src/main.rs b/gen/container1_beta1-cli/src/main.rs index 40be62d86f..57d119e5d6 100644 --- a/gen/container1_beta1-cli/src/main.rs +++ b/gen/container1_beta1-cli/src/main.rs @@ -2,169 +2,155 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_container1_beta1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - container1-beta1 [options] projects clusters-list [-p ...] [-o ] - container1-beta1 [options] projects operations-list [-p ...] [-o ] - container1-beta1 [options] projects zones-clusters-create -r ... [-p ...] [-o ] - container1-beta1 [options] projects zones-clusters-delete [-p ...] [-o ] - container1-beta1 [options] projects zones-clusters-get [-p ...] [-o ] - container1-beta1 [options] projects zones-clusters-list [-p ...] [-o ] - container1-beta1 [options] projects zones-operations-get [-p ...] [-o ] - container1-beta1 [options] projects zones-operations-list [-p ...] [-o ] - container1-beta1 [options] projects zones-tokens-get [-p ...] [-o ] - container1-beta1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_container1_beta1_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Container>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _projects_clusters_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.projects().clusters_list(&self.opt.arg_project_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _projects_clusters_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().clusters_list(opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_operations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.projects().operations_list(&self.opt.arg_project_id); - for parg in self.opt.arg_v.iter() { + fn _projects_operations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().operations_list(opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_zones_clusters_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _projects_zones_clusters_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CreateClusterRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -280,370 +266,416 @@ impl Engine { request.cluster.as_mut().unwrap().name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bearer-token", "cluster", "cluster-api-version", "container-ipv4-cidr", "creation-timestamp", "description", "enable-cloud-logging", "endpoint", "machine-type", "master-auth", "name", "network", "node-config", "node-routing-prefix-size", "num-nodes", "password", "self-link", "services-ipv4-cidr", "source-image", "status", "status-message", "user", "zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().zones_clusters_create(request, &self.opt.arg_project_id, &self.opt.arg_zone_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().zones_clusters_create(request, opt.value_of("project-id").unwrap_or(""), opt.value_of("zone-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_zones_clusters_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.projects().zones_clusters_delete(&self.opt.arg_project_id, &self.opt.arg_zone_id, &self.opt.arg_cluster_id); - for parg in self.opt.arg_v.iter() { + fn _projects_zones_clusters_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().zones_clusters_delete(opt.value_of("project-id").unwrap_or(""), opt.value_of("zone-id").unwrap_or(""), opt.value_of("cluster-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_zones_clusters_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.projects().zones_clusters_get(&self.opt.arg_project_id, &self.opt.arg_zone_id, &self.opt.arg_cluster_id); - for parg in self.opt.arg_v.iter() { + fn _projects_zones_clusters_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().zones_clusters_get(opt.value_of("project-id").unwrap_or(""), opt.value_of("zone-id").unwrap_or(""), opt.value_of("cluster-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_zones_clusters_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.projects().zones_clusters_list(&self.opt.arg_project_id, &self.opt.arg_zone_id); - for parg in self.opt.arg_v.iter() { + fn _projects_zones_clusters_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().zones_clusters_list(opt.value_of("project-id").unwrap_or(""), opt.value_of("zone-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_zones_operations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.projects().zones_operations_get(&self.opt.arg_project_id, &self.opt.arg_zone_id, &self.opt.arg_operation_id); - for parg in self.opt.arg_v.iter() { + fn _projects_zones_operations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().zones_operations_get(opt.value_of("project-id").unwrap_or(""), opt.value_of("zone-id").unwrap_or(""), opt.value_of("operation-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_zones_operations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.projects().zones_operations_list(&self.opt.arg_project_id, &self.opt.arg_zone_id); - for parg in self.opt.arg_v.iter() { + fn _projects_zones_operations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().zones_operations_list(opt.value_of("project-id").unwrap_or(""), opt.value_of("zone-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_zones_tokens_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.projects().zones_tokens_get(&self.opt.arg_master_project_id, &self.opt.arg_zone_id, &self.opt.arg_project_number, &self.opt.arg_cluster_name); - for parg in self.opt.arg_v.iter() { + fn _projects_zones_tokens_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().zones_tokens_get(opt.value_of("master-project-id").unwrap_or(""), opt.value_of("zone-id").unwrap_or(""), opt.value_of("project-number").unwrap_or(""), opt.value_of("cluster-name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_projects { - if self.opt.cmd_clusters_list { - call_result = self._projects_clusters_list(dry_run, &mut err); - } else if self.opt.cmd_operations_list { - call_result = self._projects_operations_list(dry_run, &mut err); - } else if self.opt.cmd_zones_clusters_create { - call_result = self._projects_zones_clusters_create(dry_run, &mut err); - } else if self.opt.cmd_zones_clusters_delete { - call_result = self._projects_zones_clusters_delete(dry_run, &mut err); - } else if self.opt.cmd_zones_clusters_get { - call_result = self._projects_zones_clusters_get(dry_run, &mut err); - } else if self.opt.cmd_zones_clusters_list { - call_result = self._projects_zones_clusters_list(dry_run, &mut err); - } else if self.opt.cmd_zones_operations_get { - call_result = self._projects_zones_operations_get(dry_run, &mut err); - } else if self.opt.cmd_zones_operations_list { - call_result = self._projects_zones_operations_list(dry_run, &mut err); - } else if self.opt.cmd_zones_tokens_get { - call_result = self._projects_zones_tokens_get(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("projects", Some(opt)) => { + match opt.subcommand() { + ("clusters-list", Some(opt)) => { + call_result = self._projects_clusters_list(opt, dry_run, &mut err); + }, + ("operations-list", Some(opt)) => { + call_result = self._projects_operations_list(opt, dry_run, &mut err); + }, + ("zones-clusters-create", Some(opt)) => { + call_result = self._projects_zones_clusters_create(opt, dry_run, &mut err); + }, + ("zones-clusters-delete", Some(opt)) => { + call_result = self._projects_zones_clusters_delete(opt, dry_run, &mut err); + }, + ("zones-clusters-get", Some(opt)) => { + call_result = self._projects_zones_clusters_get(opt, dry_run, &mut err); + }, + ("zones-clusters-list", Some(opt)) => { + call_result = self._projects_zones_clusters_list(opt, dry_run, &mut err); + }, + ("zones-operations-get", Some(opt)) => { + call_result = self._projects_zones_operations_get(opt, dry_run, &mut err); + }, + ("zones-operations-list", Some(opt)) => { + call_result = self._projects_zones_operations_list(opt, dry_run, &mut err); + }, + ("zones-tokens-get", Some(opt)) => { + call_result = self._projects_zones_tokens_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("projects".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -656,7 +688,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -669,7 +701,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -679,37 +711,411 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Container::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("projects", "methods: 'clusters-list', 'operations-list', 'zones-clusters-create', 'zones-clusters-delete', 'zones-clusters-get', 'zones-clusters-list', 'zones-operations-get', 'zones-operations-list' and 'zones-tokens-get'", vec![ + ("clusters-list", + Some(r##"Lists all clusters owned by a project across all zones."##), + "Details at http://byron.github.io/google-apis-rs/google_container1_beta1_cli/projects_clusters-list", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"The Google Developers Console project ID or project number."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("operations-list", + Some(r##"Lists all operations in a project, across all zones."##), + "Details at http://byron.github.io/google-apis-rs/google_container1_beta1_cli/projects_operations-list", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"The Google Developers Console project ID or project number."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("zones-clusters-create", + Some(r##"Creates a cluster, consisting of the specified number and type of Google Compute Engine instances, plus a Kubernetes master instance. + + The cluster is created in the project's default network. + + A firewall is added that allows traffic into port 443 on the master, which enables HTTPS. A firewall and a route is added for each node to allow the containers on that node to communicate with all other instances in the cluster. + + Finally, a route named k8s-iproute-10-xx-0-0 is created to track that the cluster's 10.xx.0.0/16 CIDR has been assigned."##), + "Details at http://byron.github.io/google-apis-rs/google_container1_beta1_cli/projects_zones-clusters-create", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"The Google Developers Console project ID or project number."##), + Some(true), + Some(false)), + + (Some(r##"zone-id"##), + None, + Some(r##"The name of the Google Compute Engine zone in which the cluster resides."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("zones-clusters-delete", + Some(r##"Deletes the cluster, including the Kubernetes master and all worker nodes. + + Firewalls and routes that were configured at cluster creation are also deleted."##), + "Details at http://byron.github.io/google-apis-rs/google_container1_beta1_cli/projects_zones-clusters-delete", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"The Google Developers Console project ID or project number."##), + Some(true), + Some(false)), + + (Some(r##"zone-id"##), + None, + Some(r##"The name of the Google Compute Engine zone in which the cluster resides."##), + Some(true), + Some(false)), + + (Some(r##"cluster-id"##), + None, + Some(r##"The name of the cluster to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("zones-clusters-get", + Some(r##"Gets a specific cluster."##), + "Details at http://byron.github.io/google-apis-rs/google_container1_beta1_cli/projects_zones-clusters-get", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"The Google Developers Console project ID or project number."##), + Some(true), + Some(false)), + + (Some(r##"zone-id"##), + None, + Some(r##"The name of the Google Compute Engine zone in which the cluster resides."##), + Some(true), + Some(false)), + + (Some(r##"cluster-id"##), + None, + Some(r##"The name of the cluster to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("zones-clusters-list", + Some(r##"Lists all clusters owned by a project in the specified zone."##), + "Details at http://byron.github.io/google-apis-rs/google_container1_beta1_cli/projects_zones-clusters-list", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"The Google Developers Console project ID or project number."##), + Some(true), + Some(false)), + + (Some(r##"zone-id"##), + None, + Some(r##"The name of the Google Compute Engine zone in which the cluster resides."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("zones-operations-get", + Some(r##"Gets the specified operation."##), + "Details at http://byron.github.io/google-apis-rs/google_container1_beta1_cli/projects_zones-operations-get", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"The Google Developers Console project ID or project number."##), + Some(true), + Some(false)), + + (Some(r##"zone-id"##), + None, + Some(r##"The name of the Google Compute Engine zone in which the operation resides. This is always the same zone as the cluster with which the operation is associated."##), + Some(true), + Some(false)), + + (Some(r##"operation-id"##), + None, + Some(r##"The server-assigned name of the operation."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("zones-operations-list", + Some(r##"Lists all operations in a project in a specific zone."##), + "Details at http://byron.github.io/google-apis-rs/google_container1_beta1_cli/projects_zones-operations-list", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"The Google Developers Console project ID or project number."##), + Some(true), + Some(false)), + + (Some(r##"zone-id"##), + None, + Some(r##"The name of the Google Compute Engine zone to return operations for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("zones-tokens-get", + Some(r##"Gets a compute-rw scoped OAuth2 access token for + . Authentication is performed to ensure that the caller is a member of and that the request is coming from the expected master VM for the specified cluster. See go/gke-cross-project-auth for more details."##), + "Details at http://byron.github.io/google-apis-rs/google_container1_beta1_cli/projects_zones-tokens-get", + vec![ + (Some(r##"master-project-id"##), + None, + Some(r##"The hosted master project from which this request is coming."##), + Some(true), + Some(false)), + + (Some(r##"zone-id"##), + None, + Some(r##"The zone of the specified cluster."##), + Some(true), + Some(false)), + + (Some(r##"project-number"##), + None, + Some(r##"The project number for which the access token is being requested."##), + Some(true), + Some(false)), + + (Some(r##"cluster-name"##), + None, + Some(r##"The name of the specified cluster."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("container1-beta1") + .author("Sebastian Thiel ") + .version("0.2.0+20150420") + .about("The Google Container Engine API is used for building and managing container based applications, powered by the open source Kubernetes technology.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_container1_beta1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/container1_beta1/Cargo.toml b/gen/container1_beta1/Cargo.toml index ddcd8bdc9c..9f69071c23 100644 --- a/gen/container1_beta1/Cargo.toml +++ b/gen/container1_beta1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-container1_beta1" -version = "0.1.6+20150420" +version = "0.1.7+20150420" authors = ["Sebastian Thiel "] description = "A complete library to interact with container (protocol v1beta1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/container1_beta1" @@ -15,9 +15,10 @@ keywords = ["container", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/container1_beta1/README.md b/gen/container1_beta1/README.md index e9fc88738b..a3849581a2 100644 --- a/gen/container1_beta1/README.md +++ b/gen/container1_beta1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-container1_beta1` library allows access to all features of the *Google container* service. -This documentation was generated from *container* crate version *0.1.6+20150420*, where *20150420* is the exact revision of the *container:v1beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *container* crate version *0.1.7+20150420*, where *20150420* is the exact revision of the *container:v1beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *container* *v1_beta1* API can be found at the [official documentation site](https://cloud.google.com/container-engine/docs/v1beta1/). @@ -159,7 +159,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_container1_beta1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_container1_beta1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/container1_beta1/src/cmn.rs b/gen/container1_beta1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/container1_beta1/src/cmn.rs +++ b/gen/container1_beta1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/container1_beta1/src/lib.rs b/gen/container1_beta1/src/lib.rs index aefa8c6069..4870199667 100644 --- a/gen/container1_beta1/src/lib.rs +++ b/gen/container1_beta1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *container* crate version *0.1.6+20150420*, where *20150420* is the exact revision of the *container:v1beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *container* crate version *0.1.7+20150420*, where *20150420* is the exact revision of the *container:v1beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *container* *v1_beta1* API can be found at the //! [official documentation site](https://cloud.google.com/container-engine/docs/v1beta1/). @@ -160,7 +160,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -169,7 +169,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -185,6 +184,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -301,7 +301,7 @@ impl<'a, C, A> Container Container { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -310,7 +310,7 @@ impl<'a, C, A> Container } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -944,7 +944,7 @@ impl<'a, C, A> ProjectZoneClusterGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -966,7 +966,7 @@ impl<'a, C, A> ProjectZoneClusterGetCall<'a, C, A> where C: BorrowMut ProjectOperationListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1225,7 +1225,7 @@ impl<'a, C, A> ProjectOperationListCall<'a, C, A> where C: BorrowMut ProjectZoneTokenGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1465,7 +1465,7 @@ impl<'a, C, A> ProjectZoneTokenGetCall<'a, C, A> where C: BorrowMut ProjectZoneClusterDeleteCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1723,7 +1723,7 @@ impl<'a, C, A> ProjectZoneClusterDeleteCall<'a, C, A> where C: BorrowMut ProjectClusterListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1982,7 +1982,7 @@ impl<'a, C, A> ProjectClusterListCall<'a, C, A> where C: BorrowMut ProjectZoneOperationGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2225,7 +2225,7 @@ impl<'a, C, A> ProjectZoneOperationGetCall<'a, C, A> where C: BorrowMut ProjectZoneOperationListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2486,7 +2486,7 @@ impl<'a, C, A> ProjectZoneOperationListCall<'a, C, A> where C: BorrowMut ProjectZoneClusterListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2737,7 +2737,7 @@ impl<'a, C, A> ProjectZoneClusterListCall<'a, C, A> where C: BorrowMut ProjectZoneClusterCreateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2979,11 +2980,20 @@ impl<'a, C, A> ProjectZoneClusterCreateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3006,7 +3016,7 @@ impl<'a, C, A> ProjectZoneClusterCreateCall<'a, C, A> where C: BorrowMut"] description = "A complete library to interact with Shopping Content (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/content2-cli" @@ -17,15 +17,14 @@ keywords = ["content", "google", "cli"] name = "content2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-content2] path = "../content2" diff --git a/gen/content2-cli/README.md b/gen/content2-cli/README.md index e51e60ce99..0f9a6ce119 100644 --- a/gen/content2-cli/README.md +++ b/gen/content2-cli/README.md @@ -10,61 +10,71 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *Shopping Content* API can be found at the +[official documentation site](https://developers.google.com/shopping-content/v2/). + # Usage -This documentation was generated from the *Shopping Content* API at revision *20150421*. The CLI is at version *0.1.0*. +This documentation was generated from the *Shopping Content* API at revision *20150421*. The CLI is at version *0.2.0*. ```bash - content2 [options] accounts authinfo [-p ...] [-o ] - content2 [options] accounts custombatch -r ... [-p ...] [-o ] - content2 [options] accounts delete [-p ...] - content2 [options] accounts get [-p ...] [-o ] - content2 [options] accounts insert -r ... [-p ...] [-o ] - content2 [options] accounts list [-p ...] [-o ] - content2 [options] accounts patch -r ... [-p ...] [-o ] - content2 [options] accounts update -r ... [-p ...] [-o ] - content2 [options] accountshipping custombatch -r ... [-p ...] [-o ] - content2 [options] accountshipping get [-p ...] [-o ] - content2 [options] accountshipping list [-p ...] [-o ] - content2 [options] accountshipping patch -r ... [-p ...] [-o ] - content2 [options] accountshipping update -r ... [-p ...] [-o ] - content2 [options] accountstatuses custombatch -r ... [-p ...] [-o ] - content2 [options] accountstatuses get [-p ...] [-o ] - content2 [options] accountstatuses list [-p ...] [-o ] - content2 [options] accounttax custombatch -r ... [-p ...] [-o ] - content2 [options] accounttax get [-p ...] [-o ] - content2 [options] accounttax list [-p ...] [-o ] - content2 [options] accounttax patch -r ... [-p ...] [-o ] - content2 [options] accounttax update -r ... [-p ...] [-o ] - content2 [options] datafeeds custombatch -r ... [-p ...] [-o ] - content2 [options] datafeeds delete [-p ...] - content2 [options] datafeeds get [-p ...] [-o ] - content2 [options] datafeeds insert -r ... [-p ...] [-o ] - content2 [options] datafeeds list [-p ...] [-o ] - content2 [options] datafeeds patch -r ... [-p ...] [-o ] - content2 [options] datafeeds update -r ... [-p ...] [-o ] - content2 [options] datafeedstatuses custombatch -r ... [-p ...] [-o ] - content2 [options] datafeedstatuses get [-p ...] [-o ] - content2 [options] datafeedstatuses list [-p ...] [-o ] - content2 [options] inventory custombatch -r ... [-p ...] [-o ] - content2 [options] inventory set -r ... [-p ...] [-o ] - content2 [options] products custombatch -r ... [-p ...] [-o ] - content2 [options] products delete [-p ...] - content2 [options] products get [-p ...] [-o ] - content2 [options] products insert -r ... [-p ...] [-o ] - content2 [options] products list [-p ...] [-o ] - content2 [options] productstatuses custombatch -r ... [-p ...] [-o ] - content2 [options] productstatuses get [-p ...] [-o ] - content2 [options] productstatuses list [-p ...] [-o ] +content2 [options] + accounts + authinfo [-p ]... [-o ] + custombatch (-r )... [-p ]... [-o ] + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + accountshipping + custombatch (-r )... [-p ]... [-o ] + get [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + accountstatuses + custombatch (-r )... [-p ]... [-o ] + get [-p ]... [-o ] + list [-p ]... [-o ] + accounttax + custombatch (-r )... [-p ]... [-o ] + get [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + datafeeds + custombatch (-r )... [-p ]... [-o ] + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + patch (-r )... [-p ]... [-o ] + update (-r )... [-p ]... [-o ] + datafeedstatuses + custombatch (-r )... [-p ]... [-o ] + get [-p ]... [-o ] + list [-p ]... [-o ] + inventory + custombatch (-r )... [-p ]... [-o ] + set (-r )... [-p ]... [-o ] + products + custombatch (-r )... [-p ]... [-o ] + delete [-p ]... + get [-p ]... [-o ] + insert (-r )... [-p ]... [-o ] + list [-p ]... [-o ] + productstatuses + custombatch (-r )... [-p ]... [-o ] + get [-p ]... [-o ] + list [-p ]... [-o ] content2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_content2_cli/index.html - Configuration: - --scope + [--scope ]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir A directory into which we will store our persistent data. Defaults to diff --git a/gen/content2-cli/mkdocs.yml b/gen/content2-cli/mkdocs.yml index aa18e02ba8..29a435eeca 100644 --- a/gen/content2-cli/mkdocs.yml +++ b/gen/content2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Shopping Content v0.1.0+20150421 +site_name: Shopping Content v0.2.0+20150421 site_url: http://byron.github.io/google-apis-rs/google-content2-cli site_description: Write integrating applications with bcore diff --git a/gen/content2-cli/src/cmn.rs b/gen/content2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/content2-cli/src/cmn.rs +++ b/gen/content2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Option { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option, Option), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern =", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern =.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/content2-cli/src/main.rs b/gen/content2-cli/src/main.rs index be44ec9bbc..99167d7a05 100644 --- a/gen/content2-cli/src/main.rs +++ b/gen/content2-cli/src/main.rs @@ -2,155 +2,105 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_content2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - content2 [options] accounts authinfo [-p ...] [-o ] - content2 [options] accounts custombatch -r ... [-p ...] [-o ] - content2 [options] accounts delete [-p ...] - content2 [options] accounts get [-p ...] [-o ] - content2 [options] accounts insert -r ... [-p ...] [-o ] - content2 [options] accounts list [-p ...] [-o ] - content2 [options] accounts patch -r ... [-p ...] [-o ] - content2 [options] accounts update -r ... [-p ...] [-o ] - content2 [options] accountshipping custombatch -r ... [-p ...] [-o ] - content2 [options] accountshipping get [-p ...] [-o ] - content2 [options] accountshipping list [-p ...] [-o ] - content2 [options] accountshipping patch -r ... [-p ...] [-o ] - content2 [options] accountshipping update -r ... [-p ...] [-o ] - content2 [options] accountstatuses custombatch -r ... [-p ...] [-o ] - content2 [options] accountstatuses get [-p ...] [-o ] - content2 [options] accountstatuses list [-p ...] [-o ] - content2 [options] accounttax custombatch -r ... [-p ...] [-o ] - content2 [options] accounttax get [-p ...] [-o ] - content2 [options] accounttax list [-p ...] [-o ] - content2 [options] accounttax patch -r ... [-p ...] [-o ] - content2 [options] accounttax update -r ... [-p ...] [-o ] - content2 [options] datafeeds custombatch -r ... [-p ...] [-o ] - content2 [options] datafeeds delete [-p ...] - content2 [options] datafeeds get [-p ...] [-o ] - content2 [options] datafeeds insert -r ... [-p ...] [-o ] - content2 [options] datafeeds list [-p ...] [-o ] - content2 [options] datafeeds patch -r ... [-p ...] [-o ] - content2 [options] datafeeds update -r ... [-p ...] [-o ] - content2 [options] datafeedstatuses custombatch -r ... [-p ...] [-o ] - content2 [options] datafeedstatuses get [-p ...] [-o ] - content2 [options] datafeedstatuses list [-p ...] [-o ] - content2 [options] inventory custombatch -r ... [-p ...] [-o ] - content2 [options] inventory set -r ... [-p ...] [-o ] - content2 [options] products custombatch -r ... [-p ...] [-o ] - content2 [options] products delete [-p ...] - content2 [options] products get [-p ...] [-o ] - content2 [options] products insert -r ... [-p ...] [-o ] - content2 [options] products list [-p ...] [-o ] - content2 [options] productstatuses custombatch -r ... [-p ...] [-o ] - content2 [options] productstatuses get [-p ...] [-o ] - content2 [options] productstatuses list [-p ...] [-o ] - content2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_content2_cli/index.html - -Configuration: - --scope - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::ShoppingContent>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _accounts_authinfo(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { +impl<'n, 'a> Engine<'n, 'a> { + fn _accounts_authinfo(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.accounts().authinfo(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_custombatch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounts_custombatch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AccountsCustomBatchRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -166,150 +116,158 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.accounts().custombatch(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().delete(&self.opt.arg_merchant_id, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().delete(opt.value_of("merchant-id").unwrap_or(""), opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _accounts_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().get(&self.opt.arg_merchant_id, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().get(opt.value_of("merchant-id").unwrap_or(""), opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounts_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Account::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -346,58 +304,63 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["adult-content", "id", "kind", "name", "reviews-url", "seller-id", "website-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().insert(request, &self.opt.arg_merchant_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().insert(request, opt.value_of("merchant-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounts().list(&self.opt.arg_merchant_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().list(opt.value_of("merchant-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -406,52 +369,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounts_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Account::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -488,60 +455,65 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["adult-content", "id", "kind", "name", "reviews-url", "seller-id", "website-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().patch(request, &self.opt.arg_merchant_id, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().patch(request, opt.value_of("merchant-id").unwrap_or(""), opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounts_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Account::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -578,60 +550,65 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["adult-content", "id", "kind", "name", "reviews-url", "seller-id", "website-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().update(request, &self.opt.arg_merchant_id, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().update(request, opt.value_of("merchant-id").unwrap_or(""), opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accountshipping_custombatch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accountshipping_custombatch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AccountshippingCustomBatchRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -647,107 +624,116 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.accountshipping().custombatch(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "dry-run" => { call = call.dry_run(arg_from_str(value.unwrap_or("false"), err, "dry-run", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["dry-run"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accountshipping_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accountshipping().get(&self.opt.arg_merchant_id, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accountshipping_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accountshipping().get(opt.value_of("merchant-id").unwrap_or(""), opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accountshipping_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accountshipping().list(&self.opt.arg_merchant_id); - for parg in self.opt.arg_v.iter() { + fn _accountshipping_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accountshipping().list(opt.value_of("merchant-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -756,52 +742,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accountshipping_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accountshipping_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AccountShipping::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -823,63 +813,68 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accountshipping().patch(request, &self.opt.arg_merchant_id, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accountshipping().patch(request, opt.value_of("merchant-id").unwrap_or(""), opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "dry-run" => { call = call.dry_run(arg_from_str(value.unwrap_or("false"), err, "dry-run", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["dry-run"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accountshipping_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accountshipping_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AccountShipping::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -901,63 +896,68 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accountshipping().update(request, &self.opt.arg_merchant_id, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accountshipping().update(request, opt.value_of("merchant-id").unwrap_or(""), opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "dry-run" => { call = call.dry_run(arg_from_str(value.unwrap_or("false"), err, "dry-run", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["dry-run"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accountstatuses_custombatch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accountstatuses_custombatch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AccountstatusesCustomBatchRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -973,104 +973,113 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.accountstatuses().custombatch(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accountstatuses_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accountstatuses().get(&self.opt.arg_merchant_id, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accountstatuses_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accountstatuses().get(opt.value_of("merchant-id").unwrap_or(""), opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accountstatuses_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accountstatuses().list(&self.opt.arg_merchant_id); - for parg in self.opt.arg_v.iter() { + fn _accountstatuses_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accountstatuses().list(opt.value_of("merchant-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1079,52 +1088,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounttax_custombatch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounttax_custombatch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AccounttaxCustomBatchRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1140,107 +1153,116 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.accounttax().custombatch(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "dry-run" => { call = call.dry_run(arg_from_str(value.unwrap_or("false"), err, "dry-run", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["dry-run"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounttax_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounttax().get(&self.opt.arg_merchant_id, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounttax_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounttax().get(opt.value_of("merchant-id").unwrap_or(""), opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounttax_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.accounttax().list(&self.opt.arg_merchant_id); - for parg in self.opt.arg_v.iter() { + fn _accounttax_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounttax().list(opt.value_of("merchant-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1249,52 +1271,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounttax_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounttax_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AccountTax::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1316,63 +1342,68 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounttax().patch(request, &self.opt.arg_merchant_id, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounttax().patch(request, opt.value_of("merchant-id").unwrap_or(""), opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "dry-run" => { call = call.dry_run(arg_from_str(value.unwrap_or("false"), err, "dry-run", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["dry-run"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounttax_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _accounttax_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AccountTax::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1394,63 +1425,68 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounttax().update(request, &self.opt.arg_merchant_id, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounttax().update(request, opt.value_of("merchant-id").unwrap_or(""), opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "dry-run" => { call = call.dry_run(arg_from_str(value.unwrap_or("false"), err, "dry-run", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["dry-run"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datafeeds_custombatch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _datafeeds_custombatch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::DatafeedsCustomBatchRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1466,150 +1502,158 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.datafeeds().custombatch(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datafeeds_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.datafeeds().delete(&self.opt.arg_merchant_id, &self.opt.arg_datafeed_id); - for parg in self.opt.arg_v.iter() { + fn _datafeeds_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.datafeeds().delete(opt.value_of("merchant-id").unwrap_or(""), opt.value_of("datafeed-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _datafeeds_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.datafeeds().get(&self.opt.arg_merchant_id, &self.opt.arg_datafeed_id); - for parg in self.opt.arg_v.iter() { + fn _datafeeds_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.datafeeds().get(opt.value_of("merchant-id").unwrap_or(""), opt.value_of("datafeed-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datafeeds_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _datafeeds_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Datafeed::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1712,58 +1756,63 @@ impl Engine { request.attribute_language = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attribute-language", "column-delimiter", "content-language", "content-type", "day-of-month", "fetch-schedule", "fetch-url", "file-encoding", "file-name", "format", "hour", "id", "intended-destinations", "kind", "name", "password", "quoting-mode", "target-country", "time-zone", "username", "weekday"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.datafeeds().insert(request, &self.opt.arg_merchant_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.datafeeds().insert(request, opt.value_of("merchant-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datafeeds_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.datafeeds().list(&self.opt.arg_merchant_id); - for parg in self.opt.arg_v.iter() { + fn _datafeeds_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.datafeeds().list(opt.value_of("merchant-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1772,52 +1821,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datafeeds_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _datafeeds_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Datafeed::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1920,60 +1973,65 @@ impl Engine { request.attribute_language = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attribute-language", "column-delimiter", "content-language", "content-type", "day-of-month", "fetch-schedule", "fetch-url", "file-encoding", "file-name", "format", "hour", "id", "intended-destinations", "kind", "name", "password", "quoting-mode", "target-country", "time-zone", "username", "weekday"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.datafeeds().patch(request, &self.opt.arg_merchant_id, &self.opt.arg_datafeed_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.datafeeds().patch(request, opt.value_of("merchant-id").unwrap_or(""), opt.value_of("datafeed-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datafeeds_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _datafeeds_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Datafeed::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2076,60 +2134,65 @@ impl Engine { request.attribute_language = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attribute-language", "column-delimiter", "content-language", "content-type", "day-of-month", "fetch-schedule", "fetch-url", "file-encoding", "file-name", "format", "hour", "id", "intended-destinations", "kind", "name", "password", "quoting-mode", "target-country", "time-zone", "username", "weekday"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.datafeeds().update(request, &self.opt.arg_merchant_id, &self.opt.arg_datafeed_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.datafeeds().update(request, opt.value_of("merchant-id").unwrap_or(""), opt.value_of("datafeed-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datafeedstatuses_custombatch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _datafeedstatuses_custombatch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::DatafeedstatusesCustomBatchRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2145,104 +2208,113 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.datafeedstatuses().custombatch(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datafeedstatuses_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.datafeedstatuses().get(&self.opt.arg_merchant_id, &self.opt.arg_datafeed_id); - for parg in self.opt.arg_v.iter() { + fn _datafeedstatuses_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.datafeedstatuses().get(opt.value_of("merchant-id").unwrap_or(""), opt.value_of("datafeed-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datafeedstatuses_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.datafeedstatuses().list(&self.opt.arg_merchant_id); - for parg in self.opt.arg_v.iter() { + fn _datafeedstatuses_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.datafeedstatuses().list(opt.value_of("merchant-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2251,52 +2323,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _inventory_custombatch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _inventory_custombatch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InventoryCustomBatchRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2312,60 +2388,65 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.inventory().custombatch(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _inventory_set(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _inventory_set(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InventorySetRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2420,60 +2501,65 @@ impl Engine { request.quantity = Some(arg_from_str(value.unwrap_or("-0"), err, "quantity", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["availability", "currency", "price", "quantity", "sale-price", "sale-price-effective-date", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.inventory().set(request, &self.opt.arg_merchant_id, &self.opt.arg_store_code, &self.opt.arg_product_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.inventory().set(request, opt.value_of("merchant-id").unwrap_or(""), opt.value_of("store-code").unwrap_or(""), opt.value_of("product-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _products_custombatch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _products_custombatch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ProductsCustomBatchRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2489,156 +2575,164 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.products().custombatch(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "dry-run" => { call = call.dry_run(arg_from_str(value.unwrap_or("false"), err, "dry-run", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["dry-run"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _products_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.products().delete(&self.opt.arg_merchant_id, &self.opt.arg_product_id); - for parg in self.opt.arg_v.iter() { + fn _products_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.products().delete(opt.value_of("merchant-id").unwrap_or(""), opt.value_of("product-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "dry-run" => { call = call.dry_run(arg_from_str(value.unwrap_or("false"), err, "dry-run", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["dry-run"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _products_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.products().get(&self.opt.arg_merchant_id, &self.opt.arg_product_id); - for parg in self.opt.arg_v.iter() { + fn _products_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.products().get(opt.value_of("merchant-id").unwrap_or(""), opt.value_of("product-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _products_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _products_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Product::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3013,61 +3107,66 @@ impl Engine { request.adwords_redirect = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["additional-image-links", "adult", "adwords-grouping", "adwords-labels", "adwords-redirect", "age-group", "amount", "availability", "availability-date", "brand", "channel", "color", "condition", "content-language", "currency", "custom-label0", "custom-label1", "custom-label2", "custom-label3", "custom-label4", "description", "display-ads-id", "display-ads-link", "display-ads-similar-ids", "display-ads-title", "display-ads-value", "energy-efficiency-class", "expiration-date", "gender", "google-product-category", "gtin", "id", "identifier-exists", "image-link", "installment", "is-bundle", "item-group-id", "kind", "link", "loyalty-points", "material", "mobile-link", "months", "mpn", "multipack", "name", "offer-id", "online-only", "pattern", "points-value", "price", "product-type", "ratio", "sale-price", "sale-price-effective-date", "shipping-height", "shipping-label", "shipping-length", "shipping-weight", "shipping-width", "size-system", "size-type", "sizes", "target-country", "title", "unit", "unit-pricing-base-measure", "unit-pricing-measure", "validated-destinations", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.products().insert(request, &self.opt.arg_merchant_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.products().insert(request, opt.value_of("merchant-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "dry-run" => { call = call.dry_run(arg_from_str(value.unwrap_or("false"), err, "dry-run", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["dry-run"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _products_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.products().list(&self.opt.arg_merchant_id); - for parg in self.opt.arg_v.iter() { + fn _products_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.products().list(opt.value_of("merchant-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -3076,52 +3175,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _productstatuses_custombatch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { + fn _productstatuses_custombatch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ProductstatusesCustomBatchRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3137,104 +3240,113 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.productstatuses().custombatch(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _productstatuses_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.productstatuses().get(&self.opt.arg_merchant_id, &self.opt.arg_product_id); - for parg in self.opt.arg_v.iter() { + fn _productstatuses_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.productstatuses().get(opt.value_of("merchant-id").unwrap_or(""), opt.value_of("product-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _productstatuses_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option { - let mut call = self.hub.productstatuses().list(&self.opt.arg_merchant_id); - for parg in self.opt.arg_v.iter() { + fn _productstatuses_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.productstatuses().list(opt.value_of("merchant-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -3243,193 +3355,270 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option, Option) { + fn _doit(&self, dry_run: bool) -> Result, Option> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option = None; - - if self.opt.cmd_accounts { - if self.opt.cmd_authinfo { - call_result = self._accounts_authinfo(dry_run, &mut err); - } else if self.opt.cmd_custombatch { - call_result = self._accounts_custombatch(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._accounts_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._accounts_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._accounts_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._accounts_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._accounts_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._accounts_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("accounts", Some(opt)) => { + match opt.subcommand() { + ("authinfo", Some(opt)) => { + call_result = self._accounts_authinfo(opt, dry_run, &mut err); + }, + ("custombatch", Some(opt)) => { + call_result = self._accounts_custombatch(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._accounts_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._accounts_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._accounts_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._accounts_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._accounts_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._accounts_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("accounts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("accountshipping", Some(opt)) => { + match opt.subcommand() { + ("custombatch", Some(opt)) => { + call_result = self._accountshipping_custombatch(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._accountshipping_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._accountshipping_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._accountshipping_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._accountshipping_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("accountshipping".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("accountstatuses", Some(opt)) => { + match opt.subcommand() { + ("custombatch", Some(opt)) => { + call_result = self._accountstatuses_custombatch(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._accountstatuses_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._accountstatuses_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("accountstatuses".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("accounttax", Some(opt)) => { + match opt.subcommand() { + ("custombatch", Some(opt)) => { + call_result = self._accounttax_custombatch(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._accounttax_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._accounttax_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._accounttax_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._accounttax_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("accounttax".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("datafeeds", Some(opt)) => { + match opt.subcommand() { + ("custombatch", Some(opt)) => { + call_result = self._datafeeds_custombatch(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._datafeeds_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._datafeeds_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._datafeeds_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._datafeeds_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._datafeeds_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._datafeeds_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("datafeeds".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("datafeedstatuses", Some(opt)) => { + match opt.subcommand() { + ("custombatch", Some(opt)) => { + call_result = self._datafeedstatuses_custombatch(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._datafeedstatuses_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._datafeedstatuses_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("datafeedstatuses".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("inventory", Some(opt)) => { + match opt.subcommand() { + ("custombatch", Some(opt)) => { + call_result = self._inventory_custombatch(opt, dry_run, &mut err); + }, + ("set", Some(opt)) => { + call_result = self._inventory_set(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("inventory".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("products", Some(opt)) => { + match opt.subcommand() { + ("custombatch", Some(opt)) => { + call_result = self._products_custombatch(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._products_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._products_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._products_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._products_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("products".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("productstatuses", Some(opt)) => { + match opt.subcommand() { + ("custombatch", Some(opt)) => { + call_result = self._productstatuses_custombatch(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._productstatuses_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._productstatuses_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("productstatuses".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_accountshipping { - if self.opt.cmd_custombatch { - call_result = self._accountshipping_custombatch(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._accountshipping_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._accountshipping_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._accountshipping_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._accountshipping_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_accountstatuses { - if self.opt.cmd_custombatch { - call_result = self._accountstatuses_custombatch(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._accountstatuses_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._accountstatuses_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_accounttax { - if self.opt.cmd_custombatch { - call_result = self._accounttax_custombatch(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._accounttax_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._accounttax_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._accounttax_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._accounttax_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_datafeeds { - if self.opt.cmd_custombatch { - call_result = self._datafeeds_custombatch(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._datafeeds_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._datafeeds_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._datafeeds_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._datafeeds_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._datafeeds_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._datafeeds_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_datafeedstatuses { - if self.opt.cmd_custombatch { - call_result = self._datafeedstatuses_custombatch(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._datafeedstatuses_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._datafeedstatuses_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_inventory { - if self.opt.cmd_custombatch { - call_result = self._inventory_custombatch(dry_run, &mut err); - } else if self.opt.cmd_set { - call_result = self._inventory_set(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_products { - if self.opt.cmd_custombatch { - call_result = self._products_custombatch(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._products_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._products_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._products_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._products_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_productstatuses { - if self.opt.cmd_custombatch { - call_result = self._productstatuses_custombatch(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._productstatuses_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._productstatuses_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result { + fn new(opt: ArgMatches<'a, 'n>) -> Result, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -3442,7 +3631,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -3455,7 +3644,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -3465,37 +3654,1226 @@ impl Engine { let engine = Engine { opt: opt, hub: api::ShoppingContent::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("accounts", "methods: 'authinfo', 'custombatch', 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("authinfo", + Some(r##"Returns information about the authenticated user."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accounts_authinfo", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("custombatch", + Some(r##"Retrieves, inserts, updates, and deletes multiple Merchant Center (sub-)accounts in a single request."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accounts_custombatch", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes a Merchant Center sub-account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accounts_delete", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"account-id"##), + None, + Some(r##"The ID of the account."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves a Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accounts_get", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"account-id"##), + None, + Some(r##"The ID of the account."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a Merchant Center sub-account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accounts_insert", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists the sub-accounts in your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accounts_list", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a Merchant Center account. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accounts_patch", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"account-id"##), + None, + Some(r##"The ID of the account."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accounts_update", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"account-id"##), + None, + Some(r##"The ID of the account."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("accountshipping", "methods: 'custombatch', 'get', 'list', 'patch' and 'update'", vec![ + ("custombatch", + Some(r##"Retrieves and updates the shipping settings of multiple accounts in a single request."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accountshipping_custombatch", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Retrieves the shipping settings of the account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accountshipping_get", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"account-id"##), + None, + Some(r##"The ID of the account for which to get/update account shipping settings."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists the shipping settings of the sub-accounts in your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accountshipping_list", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates the shipping settings of the account. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accountshipping_patch", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"account-id"##), + None, + Some(r##"The ID of the account for which to get/update account shipping settings."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates the shipping settings of the account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accountshipping_update", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"account-id"##), + None, + Some(r##"The ID of the account for which to get/update account shipping settings."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("accountstatuses", "methods: 'custombatch', 'get' and 'list'", vec![ + ("custombatch", + None, + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accountstatuses_custombatch", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Retrieves the status of a Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accountstatuses_get", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"account-id"##), + None, + Some(r##"The ID of the account."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists the statuses of the sub-accounts in your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accountstatuses_list", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("accounttax", "methods: 'custombatch', 'get', 'list', 'patch' and 'update'", vec![ + ("custombatch", + Some(r##"Retrieves and updates tax settings of multiple accounts in a single request."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accounttax_custombatch", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Retrieves the tax settings of the account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accounttax_get", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"account-id"##), + None, + Some(r##"The ID of the account for which to get/update account tax settings."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists the tax settings of the sub-accounts in your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accounttax_list", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates the tax settings of the account. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accounttax_patch", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"account-id"##), + None, + Some(r##"The ID of the account for which to get/update account tax settings."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates the tax settings of the account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/accounttax_update", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"account-id"##), + None, + Some(r##"The ID of the account for which to get/update account tax settings."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("datafeeds", "methods: 'custombatch', 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("custombatch", + None, + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/datafeeds_custombatch", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes a datafeed from your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/datafeeds_delete", + vec![ + (Some(r##"merchant-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"datafeed-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves a datafeed from your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/datafeeds_get", + vec![ + (Some(r##"merchant-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"datafeed-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Registers a datafeed with your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/datafeeds_insert", + vec![ + (Some(r##"merchant-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists the datafeeds in your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/datafeeds_list", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a datafeed of your Merchant Center account. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/datafeeds_patch", + vec![ + (Some(r##"merchant-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"datafeed-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a datafeed of your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/datafeeds_update", + vec![ + (Some(r##"merchant-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"datafeed-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("datafeedstatuses", "methods: 'custombatch', 'get' and 'list'", vec![ + ("custombatch", + None, + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/datafeedstatuses_custombatch", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Retrieves the status of a datafeed from your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/datafeedstatuses_get", + vec![ + (Some(r##"merchant-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"datafeed-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists the statuses of the datafeeds in your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/datafeedstatuses_list", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("inventory", "methods: 'custombatch' and 'set'", vec![ + ("custombatch", + Some(r##"Updates price and availability for multiple products or stores in a single request."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/inventory_custombatch", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set", + Some(r##"Updates price and availability of a product in your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/inventory_set", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"store-code"##), + None, + Some(r##"The code of the store for which to update price and availability. Use online to update price and availability of an online product."##), + Some(true), + Some(false)), + + (Some(r##"product-id"##), + None, + Some(r##"The ID of the product for which to update price and availability."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("products", "methods: 'custombatch', 'delete', 'get', 'insert' and 'list'", vec![ + ("custombatch", + Some(r##"Retrieves, inserts, and deletes multiple products in a single request."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/products_custombatch", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes a product from your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/products_delete", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"product-id"##), + None, + Some(r##"The ID of the product."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves a product from your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/products_get", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"product-id"##), + None, + Some(r##"The ID of the product."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Uploads a product to your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/products_insert", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists the products in your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/products_list", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("productstatuses", "methods: 'custombatch', 'get' and 'list'", vec![ + ("custombatch", + Some(r##"Gets the statuses of multiple products in a single request."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/productstatuses_custombatch", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Gets the status of a product from your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/productstatuses_get", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"product-id"##), + None, + Some(r##"The ID of the product."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists the statuses of the products in your Merchant Center account."##), + "Details at http://byron.github.io/google-apis-rs/google_content2_cli/productstatuses_list", + vec![ + (Some(r##"merchant-id"##), + None, + Some(r##"The ID of the managing account."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("content2") + .author("Sebastian Thiel ") + .version("0.2.0+20150421") + .about("Manage product items, inventory, and Merchant Center accounts for Google Shopping.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_content2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/content2/Cargo.toml b/gen/content2/Cargo.toml index 545a866ece..82d312fa6d 100644 --- a/gen/content2/Cargo.toml +++ b/gen/content2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-content2" -version = "0.1.6+20150421" +version = "0.1.7+20150421" authors = ["Sebastian Thiel "] description = "A complete library to interact with Shopping Content (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/content2" @@ -15,9 +15,10 @@ keywords = ["content", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/content2/README.md b/gen/content2/README.md index b94705f469..470487ebef 100644 --- a/gen/content2/README.md +++ b/gen/content2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-content2` library allows access to all features of the *Google Shopping Content* service. -This documentation was generated from *Shopping Content* crate version *0.1.6+20150421*, where *20150421* is the exact revision of the *content:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *Shopping Content* crate version *0.1.7+20150421*, where *20150421* is the exact revision of the *content:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *Shopping Content* *v2* API can be found at the [official documentation site](https://developers.google.com/shopping-content/v2/). @@ -186,7 +186,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_content2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_content2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/content2/src/cmn.rs b/gen/content2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/content2/src/cmn.rs +++ b/gen/content2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result> { + fn query_transfer_status(&mut self) -> std::result::Result> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option> { + pub fn upload(&mut self) -> Option> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/content2/src/lib.rs b/gen/content2/src/lib.rs index 6cd70bf400..dd6c86d7e8 100644 --- a/gen/content2/src/lib.rs +++ b/gen/content2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *Shopping Content* crate version *0.1.6+20150421*, where *20150421* is the exact revision of the *content:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *Shopping Content* crate version *0.1.7+20150421*, where *20150421* is the exact revision of the *content:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *Shopping Content* *v2* API can be found at the //! [official documentation site](https://developers.google.com/shopping-content/v2/). @@ -187,7 +187,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -196,7 +196,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -212,6 +211,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -334,7 +334,7 @@ impl<'a, C, A> ShoppingContent ShoppingContent { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -367,7 +367,7 @@ impl<'a, C, A> ShoppingContent } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -3826,6 +3826,7 @@ impl<'a, C, A> AccounttaxCustombatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, AccounttaxCustomBatchResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3859,11 +3860,20 @@ impl<'a, C, A> AccounttaxCustombatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3886,7 +3896,7 @@ impl<'a, C, A> AccounttaxCustombatchCall<'a, C, A> where C: BorrowMut AccounttaxPatchCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AccountTax)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4126,11 +4137,20 @@ impl<'a, C, A> AccounttaxPatchCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4153,7 +4173,7 @@ impl<'a, C, A> AccounttaxPatchCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4409,7 +4429,7 @@ impl<'a, C, A> AccounttaxListCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4431,7 +4451,7 @@ impl<'a, C, A> AccounttaxListCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4617,6 +4637,7 @@ impl<'a, C, A> AccounttaxUpdateCall<'a, C, A> where C: BorrowMut, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AccountTax)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4676,11 +4697,20 @@ impl<'a, C, A> AccounttaxUpdateCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4703,7 +4733,7 @@ impl<'a, C, A> AccounttaxUpdateCall<'a, C, A> where C: BorrowMut, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4951,7 +4981,7 @@ impl<'a, C, A> AccounttaxGetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4973,7 +5003,7 @@ impl<'a, C, A> AccounttaxGetCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5202,7 +5232,7 @@ impl<'a, C, A> DatafeedstatuseGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5224,7 +5254,7 @@ impl<'a, C, A> DatafeedstatuseGetCall<'a, C, A> where C: BorrowMut DatafeedstatuseListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5481,7 +5511,7 @@ impl<'a, C, A> DatafeedstatuseListCall<'a, C, A> where C: BorrowMut DatafeedstatuseCustombatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, DatafeedstatusesCustomBatchResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5691,11 +5722,20 @@ impl<'a, C, A> DatafeedstatuseCustombatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5718,7 +5758,7 @@ impl<'a, C, A> DatafeedstatuseCustombatchCall<'a, C, A> where C: BorrowMut DatafeedCustombatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, DatafeedsCustomBatchResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5916,11 +5957,20 @@ impl<'a, C, A> DatafeedCustombatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5943,7 +5993,7 @@ impl<'a, C, A> DatafeedCustombatchCall<'a, C, A> where C: BorrowMut DatafeedGetCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6186,7 +6236,7 @@ impl<'a, C, A> DatafeedGetCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6364,6 +6414,7 @@ impl<'a, C, A> DatafeedPatchCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Datafeed)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6420,11 +6471,20 @@ impl<'a, C, A> DatafeedPatchCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6447,7 +6507,7 @@ impl<'a, C, A> DatafeedPatchCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6685,7 +6745,7 @@ impl<'a, C, A> DatafeedDeleteCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6707,7 +6767,7 @@ impl<'a, C, A> DatafeedDeleteCall<'a, C, A> where C: BorrowMut, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6874,6 +6934,7 @@ impl<'a, C, A> DatafeedInsertCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Datafeed)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6929,11 +6990,20 @@ impl<'a, C, A> DatafeedInsertCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6956,7 +7026,7 @@ impl<'a, C, A> DatafeedInsertCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7194,7 +7264,7 @@ impl<'a, C, A> DatafeedListCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7216,7 +7286,7 @@ impl<'a, C, A> DatafeedListCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7400,6 +7470,7 @@ impl<'a, C, A> DatafeedUpdateCall<'a, C, A> where C: BorrowMut, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Datafeed)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7456,11 +7527,20 @@ impl<'a, C, A> DatafeedUpdateCall<'a, C, A> where C: BorrowMut, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7483,7 +7563,7 @@ impl<'a, C, A> DatafeedUpdateCall<'a, C, A> where C: BorrowMut, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7722,7 +7802,7 @@ impl<'a, C, A> ProductstatuseGetCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7744,7 +7824,7 @@ impl<'a, C, A> ProductstatuseGetCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7981,7 +8061,7 @@ impl<'a, C, A> ProductstatuseListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8003,7 +8083,7 @@ impl<'a, C, A> ProductstatuseListCall<'a, C, A> where C: BorrowMut ProductstatuseCustombatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, ProductstatusesCustomBatchResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8215,11 +8296,20 @@ impl<'a, C, A> ProductstatuseCustombatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8242,7 +8332,7 @@ impl<'a, C, A> ProductstatuseCustombatchCall<'a, C, A> where C: BorrowMut AccountAuthinfoCall<'a, C, A> where C: BorrowMut, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8457,7 +8547,7 @@ impl<'a, C, A> AccountAuthinfoCall<'a, C, A> where C: BorrowMut, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8617,6 +8707,7 @@ impl<'a, C, A> AccountPatchCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Account)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8673,11 +8764,20 @@ impl<'a, C, A> AccountPatchCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8700,7 +8800,7 @@ impl<'a, C, A> AccountPatchCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8941,7 +9041,7 @@ impl<'a, C, A> AccountGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8963,7 +9063,7 @@ impl<'a, C, A> AccountGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9143,6 +9243,7 @@ impl<'a, C, A> AccountUpdateCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Account)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9199,11 +9300,20 @@ impl<'a, C, A> AccountUpdateCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9226,7 +9336,7 @@ impl<'a, C, A> AccountUpdateCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9475,7 +9585,7 @@ impl<'a, C, A> AccountListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9497,7 +9607,7 @@ impl<'a, C, A> AccountListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9729,7 +9839,7 @@ impl<'a, C, A> AccountDeleteCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9751,7 +9861,7 @@ impl<'a, C, A> AccountDeleteCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9919,6 +10029,7 @@ impl<'a, C, A> AccountCustombatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, AccountsCustomBatchResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9949,11 +10060,20 @@ impl<'a, C, A> AccountCustombatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9976,7 +10096,7 @@ impl<'a, C, A> AccountCustombatchCall<'a, C, A> where C: BorrowMut AccountInsertCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Account)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10202,11 +10323,20 @@ impl<'a, C, A> AccountInsertCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10229,7 +10359,7 @@ impl<'a, C, A> AccountInsertCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -10412,6 +10542,7 @@ impl<'a, C, A> InventorySetCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, InventorySetResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10469,11 +10600,20 @@ impl<'a, C, A> InventorySetCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10496,7 +10636,7 @@ impl<'a, C, A> InventorySetCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -10696,6 +10836,7 @@ impl<'a, C, A> InventoryCustombatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, InventoryCustomBatchResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10726,11 +10867,20 @@ impl<'a, C, A> InventoryCustombatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10753,7 +10903,7 @@ impl<'a, C, A> InventoryCustombatchCall<'a, C, A> where C: BorrowMut AccountstatuseGetCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10996,7 +11146,7 @@ impl<'a, C, A> AccountstatuseGetCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11233,7 +11383,7 @@ impl<'a, C, A> AccountstatuseListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11255,7 +11405,7 @@ impl<'a, C, A> AccountstatuseListCall<'a, C, A> where C: BorrowMut AccountstatuseCustombatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, AccountstatusesCustomBatchResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11465,11 +11616,20 @@ impl<'a, C, A> AccountstatuseCustombatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11492,7 +11652,7 @@ impl<'a, C, A> AccountstatuseCustombatchCall<'a, C, A> where C: BorrowMut ProductListCall<'a, C, A> where C: BorrowMut, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11743,7 +11903,7 @@ impl<'a, C, A> ProductListCall<'a, C, A> where C: BorrowMut, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11976,7 +12136,7 @@ impl<'a, C, A> ProductGetCall<'a, C, A> where C: BorrowMut, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11998,7 +12158,7 @@ impl<'a, C, A> ProductGetCall<'a, C, A> where C: BorrowMut, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12231,7 +12391,7 @@ impl<'a, C, A> ProductDeleteCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12253,7 +12413,7 @@ impl<'a, C, A> ProductDeleteCall<'a, C, A> where C: BorrowMut, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12430,6 +12590,7 @@ impl<'a, C, A> ProductCustombatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, ProductsCustomBatchResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12463,11 +12624,20 @@ impl<'a, C, A> ProductCustombatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12490,7 +12660,7 @@ impl<'a, C, A> ProductCustombatchCall<'a, C, A> where C: BorrowMut ProductInsertCall<'a, C, A> where C: BorrowMut, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Product)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12728,11 +12899,20 @@ impl<'a, C, A> ProductInsertCall<'a, C, A> where C: BorrowMut, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12755,7 +12935,7 @@ impl<'a, C, A> ProductInsertCall<'a, C, A> where C: BorrowMut, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -13001,7 +13181,7 @@ impl<'a, C, A> AccountshippingListCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13023,7 +13203,7 @@ impl<'a, C, A> AccountshippingListCall<'a, C, A> where C: BorrowMut AccountshippingPatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, AccountShipping)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13268,11 +13449,20 @@ impl<'a, C, A> AccountshippingPatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13295,7 +13485,7 @@ impl<'a, C, A> AccountshippingPatchCall<'a, C, A> where C: BorrowMut AccountshippingUpdateCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, AccountShipping)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13555,11 +13746,20 @@ impl<'a, C, A> AccountshippingUpdateCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13582,7 +13782,7 @@ impl<'a, C, A> AccountshippingUpdateCall<'a, C, A> where C: BorrowMut AccountshippingCustombatchCall<'a, C, A> where C: BorrowMut Result<(hyper::client::Response, AccountshippingCustomBatchResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13814,11 +14015,20 @@ impl<'a, C, A> AccountshippingCustombatchCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13841,7 +14051,7 @@ impl<'a, C, A> AccountshippingCustombatchCall<'a, C, A> where C: BorrowMut AccountshippingGetCall<'a, C, A> where C: BorrowMut 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14091,7 +14301,7 @@ impl<'a, C, A> AccountshippingGetCall<'a, C, A> where C: BorrowMut"] description = "A complete library to interact with coordinate (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/coordinate1-cli" @@ -17,15 +17,14 @@ keywords = ["coordinate", "google", "cli"] name = "coordinate1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-coordinate1] path = "../coordinate1" diff --git a/gen/coordinate1-cli/README.md b/gen/coordinate1-cli/README.md index 041092d59d..8348d7a250 100644 --- a/gen/coordinate1-cli/README.md +++ b/gen/coordinate1-cli/README.md @@ -10,32 +10,39 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *coordinate* API can be found at the +[official documentation site](https://developers.google.com/coordinate/). + # Usage -This documentation was generated from the *coordinate* API at revision *20141215*. The CLI is at version *0.1.0*. +This documentation was generated from the *coordinate* API at revision *20141215*. The CLI is at version *0.2.0*. ```bash - coordinate1 [options] custom-field-def list [-p ...] [-o ] - coordinate1 [options] jobs get [-p ...] [-o ] - coordinate1 [options] jobs insert
-r <kv>... [-p <v>...] [-o <out>] - coordinate1 [options] jobs list <team-id> [-p <v>...] [-o <out>] - coordinate1 [options] jobs patch <team-id> <job-id> -r <kv>... [-p <v>...] [-o <out>] - coordinate1 [options] jobs update <team-id> <job-id> -r <kv>... [-p <v>...] [-o <out>] - coordinate1 [options] location list <team-id> <worker-email> <start-timestamp-ms> [-p <v>...] [-o <out>] - coordinate1 [options] schedule get <team-id> <job-id> [-p <v>...] [-o <out>] - coordinate1 [options] schedule patch <team-id> <job-id> -r <kv>... [-p <v>...] [-o <out>] - coordinate1 [options] schedule update <team-id> <job-id> -r <kv>... [-p <v>...] [-o <out>] - coordinate1 [options] team list [-p <v>...] [-o <out>] - coordinate1 [options] worker list <team-id> [-p <v>...] [-o <out>] +coordinate1 [options] + custom-field-def + list <team-id> [-p <v>]... [-o <out>] + jobs + get <team-id> <job-id> [-p <v>]... [-o <out>] + insert <team-id> <address> <lat> <lng> <title> (-r <kv>)... [-p <v>]... [-o <out>] + list <team-id> [-p <v>]... [-o <out>] + patch <team-id> <job-id> (-r <kv>)... [-p <v>]... [-o <out>] + update <team-id> <job-id> (-r <kv>)... [-p <v>]... [-o <out>] + location + list <team-id> <worker-email> <start-timestamp-ms> [-p <v>]... [-o <out>] + schedule + get <team-id> <job-id> [-p <v>]... [-o <out>] + patch <team-id> <job-id> (-r <kv>)... [-p <v>]... [-o <out>] + update <team-id> <job-id> (-r <kv>)... [-p <v>]... [-o <out>] + team + list [-p <v>]... [-o <out>] + worker + list <team-id> [-p <v>]... [-o <out>] coordinate1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_coordinate1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/coordinate1-cli/mkdocs.yml b/gen/coordinate1-cli/mkdocs.yml index c2c6aadba6..1672708b98 100644 --- a/gen/coordinate1-cli/mkdocs.yml +++ b/gen/coordinate1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: coordinate v0.1.0+20141215 +site_name: coordinate v0.2.0+20141215 site_url: http://byron.github.io/google-apis-rs/google-coordinate1-cli site_description: Write integrating applications with bcore diff --git a/gen/coordinate1-cli/src/cmn.rs b/gen/coordinate1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/coordinate1-cli/src/cmn.rs +++ b/gen/coordinate1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/coordinate1-cli/src/main.rs b/gen/coordinate1-cli/src/main.rs index d6f14e881c..6ad0b79781 100644 --- a/gen/coordinate1-cli/src/main.rs +++ b/gen/coordinate1-cli/src/main.rs @@ -2,172 +2,155 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_coordinate1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - coordinate1 [options] custom-field-def list <team-id> [-p <v>...] [-o <out>] - coordinate1 [options] jobs get <team-id> <job-id> [-p <v>...] [-o <out>] - coordinate1 [options] jobs insert <team-id> <address> <lat> <lng> <title> -r <kv>... [-p <v>...] [-o <out>] - coordinate1 [options] jobs list <team-id> [-p <v>...] [-o <out>] - coordinate1 [options] jobs patch <team-id> <job-id> -r <kv>... [-p <v>...] [-o <out>] - coordinate1 [options] jobs update <team-id> <job-id> -r <kv>... [-p <v>...] [-o <out>] - coordinate1 [options] location list <team-id> <worker-email> <start-timestamp-ms> [-p <v>...] [-o <out>] - coordinate1 [options] schedule get <team-id> <job-id> [-p <v>...] [-o <out>] - coordinate1 [options] schedule patch <team-id> <job-id> -r <kv>... [-p <v>...] [-o <out>] - coordinate1 [options] schedule update <team-id> <job-id> -r <kv>... [-p <v>...] [-o <out>] - coordinate1 [options] team list [-p <v>...] [-o <out>] - coordinate1 [options] worker list <team-id> [-p <v>...] [-o <out>] - coordinate1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_coordinate1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Coordinate<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _custom_field_def_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.custom_field_def().list(&self.opt.arg_team_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _custom_field_def_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.custom_field_def().list(opt.value_of("team-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _jobs_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.jobs().get(&self.opt.arg_team_id, &self.opt.arg_job_id); - for parg in self.opt.arg_v.iter() { + fn _jobs_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.jobs().get(opt.value_of("team-id").unwrap_or(""), opt.value_of("job-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _jobs_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _jobs_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Job::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -263,14 +246,15 @@ impl Engine { request.state.as_mut().unwrap().custom_fields.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address-line", "assignee", "custom-fields", "customer-name", "customer-phone-number", "id", "kind", "lat", "lng", "location", "note", "progress", "state", "title"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let lat: f64 = arg_from_str(&self.opt.arg_lat, err, "<lat>", "number"); - let lng: f64 = arg_from_str(&self.opt.arg_lng, err, "<lng>", "number"); - let mut call = self.hub.jobs().insert(request, &self.opt.arg_team_id, &self.opt.arg_address, lat, lng, &self.opt.arg_title); - for parg in self.opt.arg_v.iter() { + let lat: f64 = arg_from_str(&opt.value_of("lat").unwrap_or(""), err, "<lat>", "number"); + let lng: f64 = arg_from_str(&opt.value_of("lng").unwrap_or(""), err, "<lng>", "number"); + let mut call = self.hub.jobs().insert(request, opt.value_of("team-id").unwrap_or(""), opt.value_of("address").unwrap_or(""), lat, lng, opt.value_of("title").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "note" => { @@ -288,50 +272,54 @@ impl Engine { "assignee" => { call = call.assignee(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["note", "custom-field", "customer-phone-number", "customer-name", "assignee"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _jobs_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.jobs().list(&self.opt.arg_team_id); - for parg in self.opt.arg_v.iter() { + fn _jobs_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.jobs().list(opt.value_of("team-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -343,52 +331,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results", "min-modified-timestamp-ms"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _jobs_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _jobs_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Job::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -484,12 +476,13 @@ impl Engine { request.state.as_mut().unwrap().custom_fields.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address-line", "assignee", "custom-fields", "customer-name", "customer-phone-number", "id", "kind", "lat", "lng", "location", "note", "progress", "state", "title"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.jobs().patch(request, &self.opt.arg_team_id, &self.opt.arg_job_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.jobs().patch(request, opt.value_of("team-id").unwrap_or(""), opt.value_of("job-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "title" => { @@ -522,52 +515,56 @@ impl Engine { "address" => { call = call.address(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["customer-name", "title", "note", "assignee", "customer-phone-number", "address", "lat", "progress", "lng", "custom-field"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _jobs_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _jobs_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Job::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -663,12 +660,13 @@ impl Engine { request.state.as_mut().unwrap().custom_fields.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address-line", "assignee", "custom-fields", "customer-name", "customer-phone-number", "id", "kind", "lat", "lng", "location", "note", "progress", "state", "title"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.jobs().update(request, &self.opt.arg_team_id, &self.opt.arg_job_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.jobs().update(request, opt.value_of("team-id").unwrap_or(""), opt.value_of("job-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "title" => { @@ -701,50 +699,54 @@ impl Engine { "address" => { call = call.address(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["customer-name", "title", "note", "assignee", "customer-phone-number", "address", "lat", "progress", "lng", "custom-field"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _location_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.location().list(&self.opt.arg_team_id, &self.opt.arg_worker_email, &self.opt.arg_start_timestamp_ms); - for parg in self.opt.arg_v.iter() { + fn _location_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.location().list(opt.value_of("team-id").unwrap_or(""), opt.value_of("worker-email").unwrap_or(""), opt.value_of("start-timestamp-ms").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -753,98 +755,106 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _schedule_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.schedule().get(&self.opt.arg_team_id, &self.opt.arg_job_id); - for parg in self.opt.arg_v.iter() { + fn _schedule_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.schedule().get(opt.value_of("team-id").unwrap_or(""), opt.value_of("job-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _schedule_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _schedule_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Schedule::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -875,12 +885,13 @@ impl Engine { request.end_time = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["all-day", "duration", "end-time", "kind", "start-time"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.schedule().patch(request, &self.opt.arg_team_id, &self.opt.arg_job_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.schedule().patch(request, opt.value_of("team-id").unwrap_or(""), opt.value_of("job-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-time" => { @@ -895,52 +906,56 @@ impl Engine { "all-day" => { call = call.all_day(arg_from_str(value.unwrap_or("false"), err, "all-day", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["duration", "all-day", "end-time", "start-time"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _schedule_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _schedule_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Schedule::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -971,12 +986,13 @@ impl Engine { request.end_time = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["all-day", "duration", "end-time", "kind", "start-time"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.schedule().update(request, &self.opt.arg_team_id, &self.opt.arg_job_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.schedule().update(request, opt.value_of("team-id").unwrap_or(""), opt.value_of("job-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-time" => { @@ -991,50 +1007,54 @@ impl Engine { "all-day" => { call = call.all_day(arg_from_str(value.unwrap_or("false"), err, "all-day", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["duration", "all-day", "end-time", "start-time"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _team_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _team_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.team().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "worker" => { @@ -1046,166 +1066,209 @@ impl Engine { "admin" => { call = call.admin(arg_from_str(value.unwrap_or("false"), err, "admin", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["admin", "worker", "dispatcher"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _worker_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.worker().list(&self.opt.arg_team_id); - for parg in self.opt.arg_v.iter() { + fn _worker_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.worker().list(opt.value_of("team-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_custom_field_def { - if self.opt.cmd_list { - call_result = self._custom_field_def_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("custom-field-def", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._custom_field_def_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("custom-field-def".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("jobs", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._jobs_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._jobs_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._jobs_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._jobs_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._jobs_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("jobs".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("location", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._location_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("location".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("schedule", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._schedule_get(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._schedule_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._schedule_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("schedule".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("team", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._team_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("team".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("worker", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._worker_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("worker".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_jobs { - if self.opt.cmd_get { - call_result = self._jobs_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._jobs_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._jobs_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._jobs_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._jobs_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_location { - if self.opt.cmd_list { - call_result = self._location_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_schedule { - if self.opt.cmd_get { - call_result = self._schedule_get(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._schedule_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._schedule_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_team { - if self.opt.cmd_list { - call_result = self._team_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_worker { - if self.opt.cmd_list { - call_result = self._worker_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -1218,7 +1281,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1231,7 +1294,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1241,37 +1304,501 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Coordinate::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("custom-field-def", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves a list of custom field definitions for a team."##), + "Details at http://byron.github.io/google-apis-rs/google_coordinate1_cli/custom-field-def_list", + vec![ + (Some(r##"team-id"##), + None, + Some(r##"Team ID"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("jobs", "methods: 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Retrieves a job, including all the changes made to the job."##), + "Details at http://byron.github.io/google-apis-rs/google_coordinate1_cli/jobs_get", + vec![ + (Some(r##"team-id"##), + None, + Some(r##"Team ID"##), + Some(true), + Some(false)), + + (Some(r##"job-id"##), + None, + Some(r##"Job number"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new job. Only the state field of the job should be set."##), + "Details at http://byron.github.io/google-apis-rs/google_coordinate1_cli/jobs_insert", + vec![ + (Some(r##"team-id"##), + None, + Some(r##"Team ID"##), + Some(true), + Some(false)), + + (Some(r##"address"##), + None, + Some(r##"Job address as newline (Unix) separated string"##), + Some(true), + Some(false)), + + (Some(r##"lat"##), + None, + Some(r##"The latitude coordinate of this job's location."##), + Some(true), + Some(false)), + + (Some(r##"lng"##), + None, + Some(r##"The longitude coordinate of this job's location."##), + Some(true), + Some(false)), + + (Some(r##"title"##), + None, + Some(r##"Job title"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves jobs created or modified since the given timestamp."##), + "Details at http://byron.github.io/google-apis-rs/google_coordinate1_cli/jobs_list", + vec![ + (Some(r##"team-id"##), + None, + Some(r##"Team ID"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a job. Fields that are set in the job state will be updated. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_coordinate1_cli/jobs_patch", + vec![ + (Some(r##"team-id"##), + None, + Some(r##"Team ID"##), + Some(true), + Some(false)), + + (Some(r##"job-id"##), + None, + Some(r##"Job number"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a job. Fields that are set in the job state will be updated."##), + "Details at http://byron.github.io/google-apis-rs/google_coordinate1_cli/jobs_update", + vec![ + (Some(r##"team-id"##), + None, + Some(r##"Team ID"##), + Some(true), + Some(false)), + + (Some(r##"job-id"##), + None, + Some(r##"Job number"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("location", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves a list of locations for a worker."##), + "Details at http://byron.github.io/google-apis-rs/google_coordinate1_cli/location_list", + vec![ + (Some(r##"team-id"##), + None, + Some(r##"Team ID"##), + Some(true), + Some(false)), + + (Some(r##"worker-email"##), + None, + Some(r##"Worker email address."##), + Some(true), + Some(false)), + + (Some(r##"start-timestamp-ms"##), + None, + Some(r##"Start timestamp in milliseconds since the epoch."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("schedule", "methods: 'get', 'patch' and 'update'", vec![ + ("get", + Some(r##"Retrieves the schedule for a job."##), + "Details at http://byron.github.io/google-apis-rs/google_coordinate1_cli/schedule_get", + vec![ + (Some(r##"team-id"##), + None, + Some(r##"Team ID"##), + Some(true), + Some(false)), + + (Some(r##"job-id"##), + None, + Some(r##"Job number"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Replaces the schedule of a job with the provided schedule. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_coordinate1_cli/schedule_patch", + vec![ + (Some(r##"team-id"##), + None, + Some(r##"Team ID"##), + Some(true), + Some(false)), + + (Some(r##"job-id"##), + None, + Some(r##"Job number"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Replaces the schedule of a job with the provided schedule."##), + "Details at http://byron.github.io/google-apis-rs/google_coordinate1_cli/schedule_update", + vec![ + (Some(r##"team-id"##), + None, + Some(r##"Team ID"##), + Some(true), + Some(false)), + + (Some(r##"job-id"##), + None, + Some(r##"Job number"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("team", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves a list of teams for a user."##), + "Details at http://byron.github.io/google-apis-rs/google_coordinate1_cli/team_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("worker", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves a list of workers in a team."##), + "Details at http://byron.github.io/google-apis-rs/google_coordinate1_cli/worker_list", + vec![ + (Some(r##"team-id"##), + None, + Some(r##"Team ID"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("coordinate1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20141215") + .about("Lets you view and manage jobs in a Coordinate team.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_coordinate1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/coordinate1/Cargo.toml b/gen/coordinate1/Cargo.toml index 73062e9b0f..0dee925d5a 100644 --- a/gen/coordinate1/Cargo.toml +++ b/gen/coordinate1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-coordinate1" -version = "0.1.6+20141215" +version = "0.1.7+20141215" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with coordinate (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/coordinate1" @@ -15,9 +15,10 @@ keywords = ["coordinate", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/coordinate1/README.md b/gen/coordinate1/README.md index 39e6a599cf..5b2a55820e 100644 --- a/gen/coordinate1/README.md +++ b/gen/coordinate1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-coordinate1` library allows access to all features of the *Google coordinate* service. -This documentation was generated from *coordinate* crate version *0.1.6+20141215*, where *20141215* is the exact revision of the *coordinate:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *coordinate* crate version *0.1.7+20141215*, where *20141215* is the exact revision of the *coordinate:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *coordinate* *v1* API can be found at the [official documentation site](https://developers.google.com/coordinate/). @@ -187,7 +187,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_coordinate1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_coordinate1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/coordinate1/src/cmn.rs b/gen/coordinate1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/coordinate1/src/cmn.rs +++ b/gen/coordinate1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/coordinate1/src/lib.rs b/gen/coordinate1/src/lib.rs index 659b062142..b2668e3724 100644 --- a/gen/coordinate1/src/lib.rs +++ b/gen/coordinate1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *coordinate* crate version *0.1.6+20141215*, where *20141215* is the exact revision of the *coordinate:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *coordinate* crate version *0.1.7+20141215*, where *20141215* is the exact revision of the *coordinate:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *coordinate* *v1* API can be found at the //! [official documentation site](https://developers.google.com/coordinate/). @@ -188,7 +188,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -197,7 +197,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -213,6 +212,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -349,7 +349,7 @@ impl<'a, C, A> Coordinate<C, A> Coordinate { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -373,7 +373,7 @@ impl<'a, C, A> Coordinate<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1415,7 +1415,7 @@ impl<'a, C, A> JobGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth2 if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1437,7 +1437,7 @@ impl<'a, C, A> JobGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth2 access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1637,6 +1637,7 @@ impl<'a, C, A> JobUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Job)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1727,11 +1728,20 @@ impl<'a, C, A> JobUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1754,7 +1764,7 @@ impl<'a, C, A> JobUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2037,6 +2047,7 @@ impl<'a, C, A> JobPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Job)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2127,11 +2138,20 @@ impl<'a, C, A> JobPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2154,7 +2174,7 @@ impl<'a, C, A> JobPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2479,7 +2499,7 @@ impl<'a, C, A> JobListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2501,7 +2521,7 @@ impl<'a, C, A> JobListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2705,6 +2725,7 @@ impl<'a, C, A> JobInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Job)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2783,11 +2804,20 @@ impl<'a, C, A> JobInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2810,7 +2840,7 @@ impl<'a, C, A> JobInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3076,6 +3106,7 @@ impl<'a, C, A> ScheduleUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Schedule)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3144,11 +3175,20 @@ impl<'a, C, A> ScheduleUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3171,7 +3211,7 @@ impl<'a, C, A> ScheduleUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3399,6 +3439,7 @@ impl<'a, C, A> SchedulePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Schedule)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3467,11 +3508,20 @@ impl<'a, C, A> SchedulePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3494,7 +3544,7 @@ impl<'a, C, A> SchedulePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3763,7 +3813,7 @@ impl<'a, C, A> ScheduleGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3785,7 +3835,7 @@ impl<'a, C, A> ScheduleGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4012,7 +4062,7 @@ impl<'a, C, A> WorkerListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4034,7 +4084,7 @@ impl<'a, C, A> WorkerListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4265,7 +4315,7 @@ impl<'a, C, A> LocationListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4287,7 +4337,7 @@ impl<'a, C, A> LocationListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4527,7 +4577,7 @@ impl<'a, C, A> TeamListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4549,7 +4599,7 @@ impl<'a, C, A> TeamListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4777,7 +4827,7 @@ impl<'a, C, A> CustomFieldDefListCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4799,7 +4849,7 @@ impl<'a, C, A> CustomFieldDefListCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/customsearch1-cli/Cargo.toml b/gen/customsearch1-cli/Cargo.toml index e162d068c6..922ac25183 100644 --- a/gen/customsearch1-cli/Cargo.toml +++ b/gen/customsearch1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-customsearch1-cli" -version = "0.1.0+20131205" +version = "0.2.0+20131205" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with customsearch (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/customsearch1-cli" @@ -17,15 +17,14 @@ keywords = ["customsearch", "google", "cli"] name = "customsearch1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-customsearch1] path = "../customsearch1" diff --git a/gen/customsearch1-cli/README.md b/gen/customsearch1-cli/README.md index 3a05c8cd45..ecbcf77305 100644 --- a/gen/customsearch1-cli/README.md +++ b/gen/customsearch1-cli/README.md @@ -10,17 +10,19 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *customsearch* API can be found at the +[official documentation site](https://developers.google.com/custom-search/v1/using_rest). + # Usage -This documentation was generated from the *customsearch* API at revision *20131205*. The CLI is at version *0.1.0*. +This documentation was generated from the *customsearch* API at revision *20131205*. The CLI is at version *0.2.0*. ```bash - customsearch1 [options] cse list <q> [-p <v>...] [-o <out>] +customsearch1 [options] + cse + list <q> [-p <v>]... [-o <out>] customsearch1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_customsearch1_cli/index.html - Configuration: --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/customsearch1-cli/mkdocs.yml b/gen/customsearch1-cli/mkdocs.yml index 4dd1951f1f..8ef1663854 100644 --- a/gen/customsearch1-cli/mkdocs.yml +++ b/gen/customsearch1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: customsearch v0.1.0+20131205 +site_name: customsearch v0.2.0+20131205 site_url: http://byron.github.io/google-apis-rs/google-customsearch1-cli site_description: Write integrating applications with bcore diff --git a/gen/customsearch1-cli/src/cmn.rs b/gen/customsearch1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/customsearch1-cli/src/cmn.rs +++ b/gen/customsearch1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/customsearch1-cli/src/main.rs b/gen/customsearch1-cli/src/main.rs index a7b76d0f5a..fa650b8fb8 100644 --- a/gen/customsearch1-cli/src/main.rs +++ b/gen/customsearch1-cli/src/main.rs @@ -2,63 +2,53 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_customsearch1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - customsearch1 [options] cse list <q> [-p <v>...] [-o <out>] - customsearch1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_customsearch1_cli/index.html - -Configuration: - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Customsearch<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _cse_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.cse().list(&self.opt.arg_q); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _cse_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.cse().list(opt.value_of("q").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start" => { @@ -154,70 +144,83 @@ impl Engine { "c2coff" => { call = call.c2coff(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["date-restrict", "or-terms", "high-range", "num", "cr", "img-type", "related-site", "gl", "search-type", "file-type", "start", "img-dominant-color", "lr", "site-search", "cref", "sort", "safe", "c2coff", "googlehost", "hq", "exact-terms", "hl", "low-range", "img-size", "img-color-type", "rights", "exclude-terms", "filter", "link-site", "cx", "site-search-filter"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_cse { - if self.opt.cmd_list { - call_result = self._cse_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("cse", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._cse_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("cse".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -230,7 +233,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -243,7 +246,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -253,37 +256,143 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Customsearch::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("cse", "methods: 'list'", vec![ + ("list", + Some(r##"Returns metadata about the search performed, metadata about the custom search engine used for the search, and the search results."##), + "Details at http://byron.github.io/google-apis-rs/google_customsearch1_cli/cse_list", + vec![ + (Some(r##"q"##), + None, + Some(r##"Query"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("customsearch1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20131205") + .about("Lets you search over a website or collection of websites") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_customsearch1_cli") + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/customsearch1/Cargo.toml b/gen/customsearch1/Cargo.toml index 94c8a26f97..d17af91068 100644 --- a/gen/customsearch1/Cargo.toml +++ b/gen/customsearch1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-customsearch1" -version = "0.1.6+20131205" +version = "0.1.7+20131205" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with customsearch (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/customsearch1" @@ -15,9 +15,10 @@ keywords = ["customsearch", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/customsearch1/README.md b/gen/customsearch1/README.md index b89971b1e6..42de7e8e3d 100644 --- a/gen/customsearch1/README.md +++ b/gen/customsearch1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-customsearch1` library allows access to all features of the *Google customsearch* service. -This documentation was generated from *customsearch* crate version *0.1.6+20131205*, where *20131205* is the exact revision of the *customsearch:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *customsearch* crate version *0.1.7+20131205*, where *20131205* is the exact revision of the *customsearch:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *customsearch* *v1* API can be found at the [official documentation site](https://developers.google.com/custom-search/v1/using_rest). @@ -188,7 +188,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_customsearch1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_customsearch1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/customsearch1/src/cmn.rs b/gen/customsearch1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/customsearch1/src/cmn.rs +++ b/gen/customsearch1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/customsearch1/src/lib.rs b/gen/customsearch1/src/lib.rs index e2bc4a8c6d..004a80f610 100644 --- a/gen/customsearch1/src/lib.rs +++ b/gen/customsearch1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *customsearch* crate version *0.1.6+20131205*, where *20131205* is the exact revision of the *customsearch:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *customsearch* crate version *0.1.7+20131205*, where *20131205* is the exact revision of the *customsearch:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *customsearch* *v1* API can be found at the //! [official documentation site](https://developers.google.com/custom-search/v1/using_rest). @@ -189,7 +189,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -198,7 +198,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -214,6 +213,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -339,7 +339,7 @@ impl<'a, C, A> Customsearch<C, A> Customsearch { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -348,7 +348,7 @@ impl<'a, C, A> Customsearch<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1099,7 +1099,7 @@ impl<'a, C, A> CseListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1107,7 +1107,7 @@ impl<'a, C, A> CseListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); diff --git a/gen/datastore1_beta2-cli/Cargo.toml b/gen/datastore1_beta2-cli/Cargo.toml index d14f641f54..1aafcc455a 100644 --- a/gen/datastore1_beta2-cli/Cargo.toml +++ b/gen/datastore1_beta2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-datastore1_beta2-cli" -version = "0.1.0+20150402" +version = "0.2.0+20150402" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with datastore (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/datastore1_beta2-cli" @@ -17,15 +17,14 @@ keywords = ["datastore", "google", "cli"] name = "datastore1-beta2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-datastore1_beta2] path = "../datastore1_beta2" diff --git a/gen/datastore1_beta2-cli/README.md b/gen/datastore1_beta2-cli/README.md index b0df2b114a..af6333951b 100644 --- a/gen/datastore1_beta2-cli/README.md +++ b/gen/datastore1_beta2-cli/README.md @@ -10,26 +10,28 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *datastore* API can be found at the +[official documentation site](https://developers.google.com/datastore/). + # Usage -This documentation was generated from the *datastore* API at revision *20150402*. The CLI is at version *0.1.0*. +This documentation was generated from the *datastore* API at revision *20150402*. The CLI is at version *0.2.0*. ```bash - datastore1-beta2 [options] datasets allocate-ids <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - datastore1-beta2 [options] datasets begin-transaction <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - datastore1-beta2 [options] datasets commit <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - datastore1-beta2 [options] datasets lookup <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - datastore1-beta2 [options] datasets rollback <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - datastore1-beta2 [options] datasets run-query <dataset-id> -r <kv>... [-p <v>...] [-o <out>] +datastore1-beta2 [options] + datasets + allocate-ids <dataset-id> (-r <kv>)... [-p <v>]... [-o <out>] + begin-transaction <dataset-id> (-r <kv>)... [-p <v>]... [-o <out>] + commit <dataset-id> (-r <kv>)... [-p <v>]... [-o <out>] + lookup <dataset-id> (-r <kv>)... [-p <v>]... [-o <out>] + rollback <dataset-id> (-r <kv>)... [-p <v>]... [-o <out>] + run-query <dataset-id> (-r <kv>)... [-p <v>]... [-o <out>] datastore1-beta2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_datastore1_beta2_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/datastore1_beta2-cli/mkdocs.yml b/gen/datastore1_beta2-cli/mkdocs.yml index 9a14b571fb..e01497ea88 100644 --- a/gen/datastore1_beta2-cli/mkdocs.yml +++ b/gen/datastore1_beta2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: datastore v0.1.0+20150402 +site_name: datastore v0.2.0+20150402 site_url: http://byron.github.io/google-apis-rs/google-datastore1_beta2-cli site_description: Write integrating applications with bcore diff --git a/gen/datastore1_beta2-cli/src/cmn.rs b/gen/datastore1_beta2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/datastore1_beta2-cli/src/cmn.rs +++ b/gen/datastore1_beta2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/datastore1_beta2-cli/src/main.rs b/gen/datastore1_beta2-cli/src/main.rs index aca75dd409..7bac581d79 100644 --- a/gen/datastore1_beta2-cli/src/main.rs +++ b/gen/datastore1_beta2-cli/src/main.rs @@ -2,74 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_datastore1_beta2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - datastore1-beta2 [options] datasets allocate-ids <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - datastore1-beta2 [options] datasets begin-transaction <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - datastore1-beta2 [options] datasets commit <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - datastore1-beta2 [options] datasets lookup <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - datastore1-beta2 [options] datasets rollback <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - datastore1-beta2 [options] datasets run-query <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - datastore1-beta2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_datastore1_beta2_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Datastore<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _datasets_allocate_ids(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _datasets_allocate_ids(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AllocateIdsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -85,60 +66,65 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.datasets().allocate_ids(request, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.datasets().allocate_ids(request, opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_begin_transaction(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _datasets_begin_transaction(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::BeginTransactionRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -157,60 +143,65 @@ impl Engine { request.isolation_level = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["isolation-level"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.datasets().begin_transaction(request, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.datasets().begin_transaction(request, opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_commit(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _datasets_commit(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CommitRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -245,60 +236,65 @@ impl Engine { request.mutation.as_mut().unwrap().force = Some(arg_from_str(value.unwrap_or("false"), err, "mutation.force", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["force", "ignore-read-only", "mode", "mutation", "transaction"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.datasets().commit(request, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.datasets().commit(request, opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_lookup(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _datasets_lookup(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::LookupRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -328,60 +324,65 @@ impl Engine { request.read_options.as_mut().unwrap().read_consistency = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["read-consistency", "read-options", "transaction"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.datasets().lookup(request, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.datasets().lookup(request, opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_rollback(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _datasets_rollback(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::RollbackRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -400,60 +401,65 @@ impl Engine { request.transaction = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["transaction"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.datasets().rollback(request, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.datasets().rollback(request, opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_run_query(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _datasets_run_query(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::RunQueryRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -667,91 +673,110 @@ impl Engine { request.read_options.as_mut().unwrap().read_consistency = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["allow-literal", "blob-key-value", "blob-value", "boolean-value", "composite-filter", "dataset-id", "date-time-value", "double-value", "end-cursor", "entity-value", "filter", "gql-query", "indexed", "integer-value", "key", "key-value", "limit", "meaning", "name", "namespace", "offset", "operator", "partition-id", "property", "property-filter", "query", "query-string", "read-consistency", "read-options", "start-cursor", "string-value", "transaction", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.datasets().run_query(request, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.datasets().run_query(request, opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_datasets { - if self.opt.cmd_allocate_ids { - call_result = self._datasets_allocate_ids(dry_run, &mut err); - } else if self.opt.cmd_begin_transaction { - call_result = self._datasets_begin_transaction(dry_run, &mut err); - } else if self.opt.cmd_commit { - call_result = self._datasets_commit(dry_run, &mut err); - } else if self.opt.cmd_lookup { - call_result = self._datasets_lookup(dry_run, &mut err); - } else if self.opt.cmd_rollback { - call_result = self._datasets_rollback(dry_run, &mut err); - } else if self.opt.cmd_run_query { - call_result = self._datasets_run_query(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("datasets", Some(opt)) => { + match opt.subcommand() { + ("allocate-ids", Some(opt)) => { + call_result = self._datasets_allocate_ids(opt, dry_run, &mut err); + }, + ("begin-transaction", Some(opt)) => { + call_result = self._datasets_begin_transaction(opt, dry_run, &mut err); + }, + ("commit", Some(opt)) => { + call_result = self._datasets_commit(opt, dry_run, &mut err); + }, + ("lookup", Some(opt)) => { + call_result = self._datasets_lookup(opt, dry_run, &mut err); + }, + ("rollback", Some(opt)) => { + call_result = self._datasets_rollback(opt, dry_run, &mut err); + }, + ("run-query", Some(opt)) => { + call_result = self._datasets_run_query(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("datasets".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -764,7 +789,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -777,7 +802,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -787,37 +812,294 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Datastore::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("datasets", "methods: 'allocate-ids', 'begin-transaction', 'commit', 'lookup', 'rollback' and 'run-query'", vec![ + ("allocate-ids", + Some(r##"Allocate IDs for incomplete keys (useful for referencing an entity before it is inserted)."##), + "Details at http://byron.github.io/google-apis-rs/google_datastore1_beta2_cli/datasets_allocate-ids", + vec![ + (Some(r##"dataset-id"##), + None, + Some(r##"Identifies the dataset."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("begin-transaction", + Some(r##"Begin a new transaction."##), + "Details at http://byron.github.io/google-apis-rs/google_datastore1_beta2_cli/datasets_begin-transaction", + vec![ + (Some(r##"dataset-id"##), + None, + Some(r##"Identifies the dataset."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("commit", + Some(r##"Commit a transaction, optionally creating, deleting or modifying some entities."##), + "Details at http://byron.github.io/google-apis-rs/google_datastore1_beta2_cli/datasets_commit", + vec![ + (Some(r##"dataset-id"##), + None, + Some(r##"Identifies the dataset."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("lookup", + Some(r##"Look up some entities by key."##), + "Details at http://byron.github.io/google-apis-rs/google_datastore1_beta2_cli/datasets_lookup", + vec![ + (Some(r##"dataset-id"##), + None, + Some(r##"Identifies the dataset."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("rollback", + Some(r##"Roll back a transaction."##), + "Details at http://byron.github.io/google-apis-rs/google_datastore1_beta2_cli/datasets_rollback", + vec![ + (Some(r##"dataset-id"##), + None, + Some(r##"Identifies the dataset."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("run-query", + Some(r##"Query for entities."##), + "Details at http://byron.github.io/google-apis-rs/google_datastore1_beta2_cli/datasets_run-query", + vec![ + (Some(r##"dataset-id"##), + None, + Some(r##"Identifies the dataset."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("datastore1-beta2") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150402") + .about("API for accessing Google Cloud Datastore.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_datastore1_beta2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/datastore1_beta2/Cargo.toml b/gen/datastore1_beta2/Cargo.toml index 9664329771..c109ce37ff 100644 --- a/gen/datastore1_beta2/Cargo.toml +++ b/gen/datastore1_beta2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-datastore1_beta2" -version = "0.1.6+20150402" +version = "0.1.7+20150402" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with datastore (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/datastore1_beta2" @@ -15,9 +15,10 @@ keywords = ["datastore", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/datastore1_beta2/README.md b/gen/datastore1_beta2/README.md index ad39db9017..a4968c2e1d 100644 --- a/gen/datastore1_beta2/README.md +++ b/gen/datastore1_beta2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-datastore1_beta2` library allows access to all features of the *Google datastore* service. -This documentation was generated from *datastore* crate version *0.1.6+20150402*, where *20150402* is the exact revision of the *datastore:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *datastore* crate version *0.1.7+20150402*, where *20150402* is the exact revision of the *datastore:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *datastore* *v1_beta2* API can be found at the [official documentation site](https://developers.google.com/datastore/). @@ -163,7 +163,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_datastore1_beta2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_datastore1_beta2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/datastore1_beta2/src/cmn.rs b/gen/datastore1_beta2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/datastore1_beta2/src/cmn.rs +++ b/gen/datastore1_beta2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/datastore1_beta2/src/lib.rs b/gen/datastore1_beta2/src/lib.rs index b7064055b3..d575b55034 100644 --- a/gen/datastore1_beta2/src/lib.rs +++ b/gen/datastore1_beta2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *datastore* crate version *0.1.6+20150402*, where *20150402* is the exact revision of the *datastore:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *datastore* crate version *0.1.7+20150402*, where *20150402* is the exact revision of the *datastore:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *datastore* *v1_beta2* API can be found at the //! [official documentation site](https://developers.google.com/datastore/). @@ -164,7 +164,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -173,7 +173,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -189,6 +188,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -319,7 +319,7 @@ impl<'a, C, A> Datastore<C, A> Datastore { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -328,7 +328,7 @@ impl<'a, C, A> Datastore<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1264,6 +1264,7 @@ impl<'a, C, A> DatasetCommitCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CommitResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1319,11 +1320,20 @@ impl<'a, C, A> DatasetCommitCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1346,7 +1356,7 @@ impl<'a, C, A> DatasetCommitCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1527,6 +1537,7 @@ impl<'a, C, A> DatasetAllocateIdCall<'a, C, A> where C: BorrowMut<hyper::Client> /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AllocateIdsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1582,11 +1593,20 @@ impl<'a, C, A> DatasetAllocateIdCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1609,7 +1629,7 @@ impl<'a, C, A> DatasetAllocateIdCall<'a, C, A> where C: BorrowMut<hyper::Client> request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1790,6 +1810,7 @@ impl<'a, C, A> DatasetRollbackCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, RollbackResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1845,11 +1866,20 @@ impl<'a, C, A> DatasetRollbackCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1872,7 +1902,7 @@ impl<'a, C, A> DatasetRollbackCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2053,6 +2083,7 @@ impl<'a, C, A> DatasetLookupCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LookupResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2108,11 +2139,20 @@ impl<'a, C, A> DatasetLookupCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2135,7 +2175,7 @@ impl<'a, C, A> DatasetLookupCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2316,6 +2356,7 @@ impl<'a, C, A> DatasetRunQueryCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, RunQueryResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2371,11 +2412,20 @@ impl<'a, C, A> DatasetRunQueryCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2398,7 +2448,7 @@ impl<'a, C, A> DatasetRunQueryCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2579,6 +2629,7 @@ impl<'a, C, A> DatasetBeginTransactionCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, BeginTransactionResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2634,11 +2685,20 @@ impl<'a, C, A> DatasetBeginTransactionCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2661,7 +2721,7 @@ impl<'a, C, A> DatasetBeginTransactionCall<'a, C, A> where C: BorrowMut<hyper::C request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) diff --git a/gen/deploymentmanager2_beta1-cli/Cargo.toml b/gen/deploymentmanager2_beta1-cli/Cargo.toml index 79d0e6761f..f41f556b71 100644 --- a/gen/deploymentmanager2_beta1-cli/Cargo.toml +++ b/gen/deploymentmanager2_beta1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-deploymentmanager2_beta1-cli" -version = "0.1.0+20150415" +version = "0.2.0+20150415" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with deploymentmanager (protocol v2beta1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/deploymentmanager2_beta1-cli" @@ -17,15 +17,14 @@ keywords = ["deploymentmanager", "google", "cli"] name = "deploymentmanager2-beta1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-deploymentmanager2_beta1] path = "../deploymentmanager2_beta1" diff --git a/gen/deploymentmanager2_beta1-cli/README.md b/gen/deploymentmanager2_beta1-cli/README.md index 097adadf4e..f273dc35e7 100644 --- a/gen/deploymentmanager2_beta1-cli/README.md +++ b/gen/deploymentmanager2_beta1-cli/README.md @@ -10,31 +10,37 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *deploymentmanager* API can be found at the +[official documentation site](https://developers.google.com/deployment-manager/). + # Usage -This documentation was generated from the *deploymentmanager* API at revision *20150415*. The CLI is at version *0.1.0*. +This documentation was generated from the *deploymentmanager* API at revision *20150415*. The CLI is at version *0.2.0*. ```bash - deploymentmanager2-beta1 [options] deployments delete <project> <deployment> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] deployments get <project> <deployment> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] deployments insert <project> -r <kv>... [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] deployments list <project> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] manifests get <project> <deployment> <manifest> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] manifests list <project> <deployment> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] operations get <project> <operation> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] operations list <project> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] resources get <project> <deployment> <resource> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] resources list <project> <deployment> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] types list <project> [-p <v>...] [-o <out>] +deploymentmanager2-beta1 [options] + deployments + delete <project> <deployment> [-p <v>]... [-o <out>] + get <project> <deployment> [-p <v>]... [-o <out>] + insert <project> (-r <kv>)... [-p <v>]... [-o <out>] + list <project> [-p <v>]... [-o <out>] + manifests + get <project> <deployment> <manifest> [-p <v>]... [-o <out>] + list <project> <deployment> [-p <v>]... [-o <out>] + operations + get <project> <operation> [-p <v>]... [-o <out>] + list <project> [-p <v>]... [-o <out>] + resources + get <project> <deployment> <resource> [-p <v>]... [-o <out>] + list <project> <deployment> [-p <v>]... [-o <out>] + types + list <project> [-p <v>]... [-o <out>] deploymentmanager2-beta1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/deploymentmanager2_beta1-cli/mkdocs.yml b/gen/deploymentmanager2_beta1-cli/mkdocs.yml index 39d82d71c6..550cd8bd78 100644 --- a/gen/deploymentmanager2_beta1-cli/mkdocs.yml +++ b/gen/deploymentmanager2_beta1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: deploymentmanager v0.1.0+20150415 +site_name: deploymentmanager v0.2.0+20150415 site_url: http://byron.github.io/google-apis-rs/google-deploymentmanager2_beta1-cli site_description: Write integrating applications with bcore diff --git a/gen/deploymentmanager2_beta1-cli/src/cmn.rs b/gen/deploymentmanager2_beta1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/deploymentmanager2_beta1-cli/src/cmn.rs +++ b/gen/deploymentmanager2_beta1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/deploymentmanager2_beta1-cli/src/main.rs b/gen/deploymentmanager2_beta1-cli/src/main.rs index cb1ba34835..022beb9be3 100644 --- a/gen/deploymentmanager2_beta1-cli/src/main.rs +++ b/gen/deploymentmanager2_beta1-cli/src/main.rs @@ -2,171 +2,155 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_deploymentmanager2_beta1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - deploymentmanager2-beta1 [options] deployments delete <project> <deployment> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] deployments get <project> <deployment> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] deployments insert <project> -r <kv>... [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] deployments list <project> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] manifests get <project> <deployment> <manifest> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] manifests list <project> <deployment> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] operations get <project> <operation> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] operations list <project> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] resources get <project> <deployment> <resource> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] resources list <project> <deployment> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 [options] types list <project> [-p <v>...] [-o <out>] - deploymentmanager2-beta1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Deploymentmanager<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _deployments_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.deployments().delete(&self.opt.arg_project, &self.opt.arg_deployment); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _deployments_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.deployments().delete(opt.value_of("project").unwrap_or(""), opt.value_of("deployment").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _deployments_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.deployments().get(&self.opt.arg_project, &self.opt.arg_deployment); - for parg in self.opt.arg_v.iter() { + fn _deployments_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.deployments().get(opt.value_of("project").unwrap_or(""), opt.value_of("deployment").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _deployments_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _deployments_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Deployment::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -197,58 +181,63 @@ impl Engine { request.description = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["description", "id", "manifest", "name", "target-config"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.deployments().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.deployments().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _deployments_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.deployments().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _deployments_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.deployments().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -257,96 +246,104 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _manifests_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.manifests().get(&self.opt.arg_project, &self.opt.arg_deployment, &self.opt.arg_manifest); - for parg in self.opt.arg_v.iter() { + fn _manifests_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.manifests().get(opt.value_of("project").unwrap_or(""), opt.value_of("deployment").unwrap_or(""), opt.value_of("manifest").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _manifests_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.manifests().list(&self.opt.arg_project, &self.opt.arg_deployment); - for parg in self.opt.arg_v.iter() { + fn _manifests_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.manifests().list(opt.value_of("project").unwrap_or(""), opt.value_of("deployment").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -355,96 +352,104 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _operations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.operations().get(&self.opt.arg_project, &self.opt.arg_operation); - for parg in self.opt.arg_v.iter() { + fn _operations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.operations().get(opt.value_of("project").unwrap_or(""), opt.value_of("operation").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _operations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.operations().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _operations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.operations().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -453,96 +458,104 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _resources_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.resources().get(&self.opt.arg_project, &self.opt.arg_deployment, &self.opt.arg_resource); - for parg in self.opt.arg_v.iter() { + fn _resources_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.resources().get(opt.value_of("project").unwrap_or(""), opt.value_of("deployment").unwrap_or(""), opt.value_of("resource").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _resources_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.resources().list(&self.opt.arg_project, &self.opt.arg_deployment); - for parg in self.opt.arg_v.iter() { + fn _resources_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.resources().list(opt.value_of("project").unwrap_or(""), opt.value_of("deployment").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -551,50 +564,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _types_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.types().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _types_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.types().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -603,113 +620,148 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_deployments { - if self.opt.cmd_delete { - call_result = self._deployments_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._deployments_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._deployments_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._deployments_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("deployments", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._deployments_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._deployments_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._deployments_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._deployments_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("deployments".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("manifests", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._manifests_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._manifests_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("manifests".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("operations", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._operations_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._operations_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("operations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("resources", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._resources_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._resources_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("resources".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("types", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._types_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("types".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_manifests { - if self.opt.cmd_get { - call_result = self._manifests_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._manifests_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_operations { - if self.opt.cmd_get { - call_result = self._operations_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._operations_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_resources { - if self.opt.cmd_get { - call_result = self._resources_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._resources_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_types { - if self.opt.cmd_list { - call_result = self._types_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -722,7 +774,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -735,7 +787,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -745,37 +797,440 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Deploymentmanager::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("deployments", "methods: 'delete', 'get', 'insert' and 'list'", vec![ + ("delete", + Some(r##"! Deletes a deployment and all of the resources in the deployment."##), + "Details at http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1_cli/deployments_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"! The project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"deployment"##), + None, + Some(r##"! The name of the deployment for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"! Gets information about a specific deployment."##), + "Details at http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1_cli/deployments_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"! The project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"deployment"##), + None, + Some(r##"! The name of the deployment for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"! Creates a deployment and all of the resources described by the ! deployment manifest."##), + "Details at http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1_cli/deployments_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"! The project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"! Lists all deployments for a given project."##), + "Details at http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1_cli/deployments_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"! The project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("manifests", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"! Gets information about a specific manifest."##), + "Details at http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1_cli/manifests_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"! The project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"deployment"##), + None, + Some(r##"! The name of the deployment for this request."##), + Some(true), + Some(false)), + + (Some(r##"manifest"##), + None, + Some(r##"! The name of the manifest for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"! Lists all manifests for a given deployment."##), + "Details at http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1_cli/manifests_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"! The project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"deployment"##), + None, + Some(r##"! The name of the deployment for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("operations", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"! Gets information about a specific Operation."##), + "Details at http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1_cli/operations_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"! The project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"operation"##), + None, + Some(r##"! The name of the operation for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"! Lists all Operations for a project."##), + "Details at http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1_cli/operations_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"! The project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("resources", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"! Gets information about a single resource."##), + "Details at http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1_cli/resources_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"! The project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"deployment"##), + None, + Some(r##"! The name of the deployment for this request."##), + Some(true), + Some(false)), + + (Some(r##"resource"##), + None, + Some(r##"! The name of the resource for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"! Lists all resources in a given deployment."##), + "Details at http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1_cli/resources_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"! The project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"deployment"##), + None, + Some(r##"! The name of the deployment for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("types", "methods: 'list'", vec![ + ("list", + Some(r##"! Lists all Types for Deployment Manager."##), + "Details at http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1_cli/types_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"! The project ID for this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("deploymentmanager2-beta1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150415") + .about("The Deployment Manager API allows users to declaratively configure, deploy and run complex solutions on the Google Cloud Platform.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/deploymentmanager2_beta1/Cargo.toml b/gen/deploymentmanager2_beta1/Cargo.toml index c264541101..91d5e290bb 100644 --- a/gen/deploymentmanager2_beta1/Cargo.toml +++ b/gen/deploymentmanager2_beta1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-deploymentmanager2_beta1" -version = "0.1.6+20150415" +version = "0.1.7+20150415" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with deploymentmanager (protocol v2beta1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/deploymentmanager2_beta1" @@ -15,9 +15,10 @@ keywords = ["deploymentmanager", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/deploymentmanager2_beta1/README.md b/gen/deploymentmanager2_beta1/README.md index 7d0932d8ca..062fe8a9cc 100644 --- a/gen/deploymentmanager2_beta1/README.md +++ b/gen/deploymentmanager2_beta1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-deploymentmanager2_beta1` library allows access to all features of the *Google deploymentmanager* service. -This documentation was generated from *deploymentmanager* crate version *0.1.6+20150415*, where *20150415* is the exact revision of the *deploymentmanager:v2beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *deploymentmanager* crate version *0.1.7+20150415*, where *20150415* is the exact revision of the *deploymentmanager:v2beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *deploymentmanager* *v2_beta1* API can be found at the [official documentation site](https://developers.google.com/deployment-manager/). @@ -170,7 +170,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_deploymentmanager2_beta1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/deploymentmanager2_beta1/src/cmn.rs b/gen/deploymentmanager2_beta1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/deploymentmanager2_beta1/src/cmn.rs +++ b/gen/deploymentmanager2_beta1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/deploymentmanager2_beta1/src/lib.rs b/gen/deploymentmanager2_beta1/src/lib.rs index d9cbd39772..47b635010a 100644 --- a/gen/deploymentmanager2_beta1/src/lib.rs +++ b/gen/deploymentmanager2_beta1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *deploymentmanager* crate version *0.1.6+20150415*, where *20150415* is the exact revision of the *deploymentmanager:v2beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *deploymentmanager* crate version *0.1.7+20150415*, where *20150415* is the exact revision of the *deploymentmanager:v2beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *deploymentmanager* *v2_beta1* API can be found at the //! [official documentation site](https://developers.google.com/deployment-manager/). @@ -171,7 +171,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -180,7 +180,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -196,6 +195,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -322,7 +322,7 @@ impl<'a, C, A> Deploymentmanager<C, A> Deploymentmanager { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -343,7 +343,7 @@ impl<'a, C, A> Deploymentmanager<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1244,7 +1244,7 @@ impl<'a, C, A> OperationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1266,7 +1266,7 @@ impl<'a, C, A> OperationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1503,7 +1503,7 @@ impl<'a, C, A> OperationListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1525,7 +1525,7 @@ impl<'a, C, A> OperationListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1708,6 +1708,7 @@ impl<'a, C, A> DeploymentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1763,11 +1764,20 @@ impl<'a, C, A> DeploymentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1790,7 +1800,7 @@ impl<'a, C, A> DeploymentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2021,7 +2031,7 @@ impl<'a, C, A> DeploymentGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2043,7 +2053,7 @@ impl<'a, C, A> DeploymentGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2280,7 +2290,7 @@ impl<'a, C, A> DeploymentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2302,7 +2312,7 @@ impl<'a, C, A> DeploymentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2535,7 +2545,7 @@ impl<'a, C, A> DeploymentDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2557,7 +2567,7 @@ impl<'a, C, A> DeploymentDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2794,7 +2804,7 @@ impl<'a, C, A> TypeListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2816,7 +2826,7 @@ impl<'a, C, A> TypeListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3051,7 +3061,7 @@ impl<'a, C, A> ResourceGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3073,7 +3083,7 @@ impl<'a, C, A> ResourceGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3322,7 +3332,7 @@ impl<'a, C, A> ResourceListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3344,7 +3354,7 @@ impl<'a, C, A> ResourceListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3597,7 +3607,7 @@ impl<'a, C, A> ManifestListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3619,7 +3629,7 @@ impl<'a, C, A> ManifestListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3864,7 +3874,7 @@ impl<'a, C, A> ManifestGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3886,7 +3896,7 @@ impl<'a, C, A> ManifestGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/dfareporting2d1-cli/Cargo.toml b/gen/dfareporting2d1-cli/Cargo.toml index e413532640..52d1745e6c 100644 --- a/gen/dfareporting2d1-cli/Cargo.toml +++ b/gen/dfareporting2d1-cli/Cargo.toml @@ -17,14 +17,14 @@ keywords = ["dfareporting", "google", "cli"] name = "dfareporting2d1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -clap = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-dfareporting2d1] path = "../dfareporting2d1" diff --git a/gen/dfareporting2d1-cli/README.md b/gen/dfareporting2d1-cli/README.md index 2267c82050..5394d0e731 100644 --- a/gen/dfareporting2d1-cli/README.md +++ b/gen/dfareporting2d1-cli/README.md @@ -18,208 +18,261 @@ Everything else about the *dfareporting* API can be found at the This documentation was generated from the *dfareporting* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - dfareporting2d1 [options] account-active-ad-summaries get <profile-id> <summary-account-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] account-permission-groups get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] account-permission-groups list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] account-permissions get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] account-permissions list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] account-user-profiles get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] account-user-profiles insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] account-user-profiles list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] account-user-profiles patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] account-user-profiles update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] accounts get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] accounts list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] accounts patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] accounts update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] ads get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] ads insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] ads list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] ads patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] ads update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] advertiser-groups delete <profile-id> <id> [-p <v>...] - dfareporting2d1 [options] advertiser-groups get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] advertiser-groups insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] advertiser-groups list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] advertiser-groups patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] advertiser-groups update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] advertisers get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] advertisers insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] advertisers list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] advertisers patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] advertisers update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] browsers list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] campaign-creative-associations insert <profile-id> <campaign-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] campaign-creative-associations list <profile-id> <campaign-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] campaigns get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] campaigns insert <profile-id> <default-landing-page-name> <default-landing-page-url> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] campaigns list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] campaigns patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] campaigns update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] change-logs get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] change-logs list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] cities list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] connection-types get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] connection-types list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] content-categories delete <profile-id> <id> [-p <v>...] - dfareporting2d1 [options] content-categories get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] content-categories insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] content-categories list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] content-categories patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] content-categories update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] countries get <profile-id> <dart-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] countries list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-assets insert <profile-id> <advertiser-id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-field-values delete <profile-id> <creative-field-id> <id> [-p <v>...] - dfareporting2d1 [options] creative-field-values get <profile-id> <creative-field-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-field-values insert <profile-id> <creative-field-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-field-values list <profile-id> <creative-field-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-field-values patch <profile-id> <creative-field-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-field-values update <profile-id> <creative-field-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-fields delete <profile-id> <id> [-p <v>...] - dfareporting2d1 [options] creative-fields get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-fields insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-fields list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-fields patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-fields update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-groups get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-groups insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-groups list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-groups patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] creative-groups update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] creatives get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] creatives insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] creatives list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] creatives patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] creatives update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] dimension-values query <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] directory-site-contacts get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] directory-site-contacts list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] directory-sites get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] directory-sites insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] directory-sites list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] event-tags delete <profile-id> <id> [-p <v>...] - dfareporting2d1 [options] event-tags get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] event-tags insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] event-tags list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] event-tags patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] event-tags update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] files get <report-id> <file-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] files list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-activities delete <profile-id> <id> [-p <v>...] - dfareporting2d1 [options] floodlight-activities generatetag <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-activities get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-activities insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-activities list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-activities patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-activities update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-activity-groups delete <profile-id> <id> [-p <v>...] - dfareporting2d1 [options] floodlight-activity-groups get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-activity-groups insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-activity-groups list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-activity-groups patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-activity-groups update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-configurations get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-configurations list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-configurations patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] floodlight-configurations update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] inventory-items get <profile-id> <project-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] inventory-items list <profile-id> <project-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] landing-pages delete <profile-id> <campaign-id> <id> [-p <v>...] - dfareporting2d1 [options] landing-pages get <profile-id> <campaign-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] landing-pages insert <profile-id> <campaign-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] landing-pages list <profile-id> <campaign-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] landing-pages patch <profile-id> <campaign-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] landing-pages update <profile-id> <campaign-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] metros list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] mobile-carriers get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] mobile-carriers list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] operating-system-versions get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] operating-system-versions list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] operating-systems get <profile-id> <dart-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] operating-systems list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] order-documents get <profile-id> <project-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] order-documents list <profile-id> <project-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] orders get <profile-id> <project-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] orders list <profile-id> <project-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] placement-groups get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] placement-groups insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] placement-groups list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] placement-groups patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] placement-groups update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] placement-strategies delete <profile-id> <id> [-p <v>...] - dfareporting2d1 [options] placement-strategies get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] placement-strategies insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] placement-strategies list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] placement-strategies patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] placement-strategies update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] placements generatetags <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] placements get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] placements insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] placements list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] placements patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] placements update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] platform-types get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] platform-types list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] postal-codes get <profile-id> <code> [-p <v>...] [-o <out>] - dfareporting2d1 [options] postal-codes list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] projects get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] projects list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] regions list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] remarketing-list-shares get <profile-id> <remarketing-list-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] remarketing-list-shares patch <profile-id> <remarketing-list-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] remarketing-list-shares update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] remarketing-lists get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] remarketing-lists insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] remarketing-lists list <profile-id> <advertiser-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] remarketing-lists patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] remarketing-lists update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] reports compatible-fields-query <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] reports delete <profile-id> <report-id> [-p <v>...] - dfareporting2d1 [options] reports files-get <profile-id> <report-id> <file-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] reports files-list <profile-id> <report-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] reports get <profile-id> <report-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] reports insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] reports list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] reports patch <profile-id> <report-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] reports run <profile-id> <report-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] reports update <profile-id> <report-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] sites get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] sites insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] sites list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] sites patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] sites update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] sizes get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] sizes insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] sizes list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] subaccounts get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] subaccounts insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] subaccounts list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] subaccounts patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] subaccounts update <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] targetable-remarketing-lists get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] targetable-remarketing-lists list <profile-id> <advertiser-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] user-profiles get <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] user-profiles list [-p <v>...] [-o <out>] - dfareporting2d1 [options] user-role-permission-groups get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] user-role-permission-groups list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] user-role-permissions get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] user-role-permissions list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] user-roles delete <profile-id> <id> [-p <v>...] - dfareporting2d1 [options] user-roles get <profile-id> <id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] user-roles insert <profile-id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] user-roles list <profile-id> [-p <v>...] [-o <out>] - dfareporting2d1 [options] user-roles patch <profile-id> <id> -r <kv>... [-p <v>...] [-o <out>] - dfareporting2d1 [options] user-roles update <profile-id> -r <kv>... [-p <v>...] [-o <out>] +dfareporting2d1 [options] + account-active-ad-summaries + get <profile-id> <summary-account-id> [-p <v>]... [-o <out>] + account-permission-groups + get <profile-id> <id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + account-permissions + get <profile-id> <id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + account-user-profiles + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + accounts + get <profile-id> <id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + ads + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + advertiser-groups + delete <profile-id> <id> [-p <v>]... + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + advertisers + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + browsers + list <profile-id> [-p <v>]... [-o <out>] + campaign-creative-associations + insert <profile-id> <campaign-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> <campaign-id> [-p <v>]... [-o <out>] + campaigns + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> <default-landing-page-name> <default-landing-page-url> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + change-logs + get <profile-id> <id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + cities + list <profile-id> [-p <v>]... [-o <out>] + connection-types + get <profile-id> <id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + content-categories + delete <profile-id> <id> [-p <v>]... + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + countries + get <profile-id> <dart-id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + creative-assets + insert <profile-id> <advertiser-id> (-r <kv>)... (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + creative-field-values + delete <profile-id> <creative-field-id> <id> [-p <v>]... + get <profile-id> <creative-field-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> <creative-field-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> <creative-field-id> [-p <v>]... [-o <out>] + patch <profile-id> <creative-field-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> <creative-field-id> (-r <kv>)... [-p <v>]... [-o <out>] + creative-fields + delete <profile-id> <id> [-p <v>]... + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + creative-groups + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + creatives + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + dimension-values + query <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + directory-site-contacts + get <profile-id> <id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + directory-sites + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + event-tags + delete <profile-id> <id> [-p <v>]... + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + files + get <report-id> <file-id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + floodlight-activities + delete <profile-id> <id> [-p <v>]... + generatetag <profile-id> [-p <v>]... [-o <out>] + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + floodlight-activity-groups + delete <profile-id> <id> [-p <v>]... + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + floodlight-configurations + get <profile-id> <id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + inventory-items + get <profile-id> <project-id> <id> [-p <v>]... [-o <out>] + list <profile-id> <project-id> [-p <v>]... [-o <out>] + landing-pages + delete <profile-id> <campaign-id> <id> [-p <v>]... + get <profile-id> <campaign-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> <campaign-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> <campaign-id> [-p <v>]... [-o <out>] + patch <profile-id> <campaign-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> <campaign-id> (-r <kv>)... [-p <v>]... [-o <out>] + metros + list <profile-id> [-p <v>]... [-o <out>] + mobile-carriers + get <profile-id> <id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + operating-system-versions + get <profile-id> <id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + operating-systems + get <profile-id> <dart-id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + order-documents + get <profile-id> <project-id> <id> [-p <v>]... [-o <out>] + list <profile-id> <project-id> [-p <v>]... [-o <out>] + orders + get <profile-id> <project-id> <id> [-p <v>]... [-o <out>] + list <profile-id> <project-id> [-p <v>]... [-o <out>] + placement-groups + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + placement-strategies + delete <profile-id> <id> [-p <v>]... + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + placements + generatetags <profile-id> [-p <v>]... [-o <out>] + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + platform-types + get <profile-id> <id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + postal-codes + get <profile-id> <code> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + projects + get <profile-id> <id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + regions + list <profile-id> [-p <v>]... [-o <out>] + remarketing-list-shares + get <profile-id> <remarketing-list-id> [-p <v>]... [-o <out>] + patch <profile-id> <remarketing-list-id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + remarketing-lists + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> <advertiser-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + reports + compatible-fields-query <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + delete <profile-id> <report-id> [-p <v>]... + files-get <profile-id> <report-id> <file-id> [-p <v>]... [-o <out>] + files-list <profile-id> <report-id> [-p <v>]... [-o <out>] + get <profile-id> <report-id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <report-id> (-r <kv>)... [-p <v>]... [-o <out>] + run <profile-id> <report-id> [-p <v>]... [-o <out>] + update <profile-id> <report-id> (-r <kv>)... [-p <v>]... [-o <out>] + sites + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + sizes + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + subaccounts + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + targetable-remarketing-lists + get <profile-id> <id> [-p <v>]... [-o <out>] + list <profile-id> <advertiser-id> [-p <v>]... [-o <out>] + user-profiles + get <profile-id> [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + user-role-permission-groups + get <profile-id> <id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + user-role-permissions + get <profile-id> <id> [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + user-roles + delete <profile-id> <id> [-p <v>]... + get <profile-id> <id> [-p <v>]... [-o <out>] + insert <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <profile-id> [-p <v>]... [-o <out>] + patch <profile-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <profile-id> (-r <kv>)... [-p <v>]... [-o <out>] dfareporting2d1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/dfareporting2d1-cli/src/cmn.rs b/gen/dfareporting2d1-cli/src/cmn.rs index f07fb4dec5..3335e7b6bd 100644 --- a/gen/dfareporting2d1-cli/src/cmn.rs +++ b/gen/dfareporting2d1-cli/src/cmn.rs @@ -1,9 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -18,18 +19,70 @@ use std::default::Default; const FIELD_SEP: char = '.'; -/// Unused for now, can be used once https://github.com/kbknapp/clap-rs/issues/87 -/// is available -pub enum UploadProtocol { - Simple, - Resumable, +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } } impl AsRef<str> for UploadProtocol { fn as_ref(&self) -> &str { match *self { UploadProtocol::Simple => "simple", - UploadProtocol::Resumable => "resumable", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" } } } @@ -105,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -129,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -149,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -168,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -188,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -240,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -248,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -270,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -293,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -304,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -313,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -328,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -341,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -416,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -435,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -446,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/dfareporting2d1-cli/src/main.rs b/gen/dfareporting2d1-cli/src/main.rs index ddfbaebf25..a058cdd1f2 100644 --- a/gen/dfareporting2d1-cli/src/main.rs +++ b/gen/dfareporting2d1-cli/src/main.rs @@ -4,13 +4,14 @@ #![feature(plugin, exit_status)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] +#[macro_use] extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_dfareporting2d1 as api; use std::env; @@ -19,5910 +20,29954 @@ use clap::{App, SubCommand, Arg}; mod cmn; +use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; + +use std::default::Default; +use std::str::FromStr; + +use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; +use serde::json; +use clap::ArgMatches; + +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, + hub: api::Dfareporting<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, +} + + +impl<'n, 'a> Engine<'n, 'a> { + fn _account_active_ad_summaries_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.account_active_ad_summaries().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("summary-account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _account_permission_groups_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.account_permission_groups().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _account_permission_groups_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.account_permission_groups().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _account_permissions_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.account_permissions().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _account_permissions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.account_permissions().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _account_user_profiles_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.account_user_profiles().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _account_user_profiles_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::AccountUserProfile::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_filter_init(request: &mut api::AccountUserProfile) { + if request.advertiser_filter.is_none() { + request.advertiser_filter = Some(Default::default()); + } + } + + fn request_campaign_filter_init(request: &mut api::AccountUserProfile) { + if request.campaign_filter.is_none() { + request.campaign_filter = Some(Default::default()); + } + } + + fn request_site_filter_init(request: &mut api::AccountUserProfile) { + if request.site_filter.is_none() { + request.site_filter = Some(Default::default()); + } + } + + fn request_user_role_filter_init(request: &mut api::AccountUserProfile) { + if request.user_role_filter.is_none() { + request.user_role_filter = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "user-role-filter.object-ids" => { + request_user_role_filter_init(&mut request); + if request.user_role_filter.as_mut().unwrap().object_ids.is_none() { + request.user_role_filter.as_mut().unwrap().object_ids = Some(Default::default()); + } + request.user_role_filter.as_mut().unwrap().object_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "user-role-filter.status" => { + request_user_role_filter_init(&mut request); + request.user_role_filter.as_mut().unwrap().status = Some(value.unwrap_or("").to_string()); + }, + "user-role-filter.kind" => { + request_user_role_filter_init(&mut request); + request.user_role_filter.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_user_role_filter_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "locale" => { + request_user_role_filter_init(&mut request); + request.locale = Some(value.unwrap_or("").to_string()); + }, + "site-filter.object-ids" => { + request_site_filter_init(&mut request); + if request.site_filter.as_mut().unwrap().object_ids.is_none() { + request.site_filter.as_mut().unwrap().object_ids = Some(Default::default()); + } + request.site_filter.as_mut().unwrap().object_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "site-filter.status" => { + request_site_filter_init(&mut request); + request.site_filter.as_mut().unwrap().status = Some(value.unwrap_or("").to_string()); + }, + "site-filter.kind" => { + request_site_filter_init(&mut request); + request.site_filter.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "comments" => { + request_site_filter_init(&mut request); + request.comments = Some(value.unwrap_or("").to_string()); + }, + "trafficker-type" => { + request_site_filter_init(&mut request); + request.trafficker_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-filter.object-ids" => { + request_advertiser_filter_init(&mut request); + if request.advertiser_filter.as_mut().unwrap().object_ids.is_none() { + request.advertiser_filter.as_mut().unwrap().object_ids = Some(Default::default()); + } + request.advertiser_filter.as_mut().unwrap().object_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "advertiser-filter.status" => { + request_advertiser_filter_init(&mut request); + request.advertiser_filter.as_mut().unwrap().status = Some(value.unwrap_or("").to_string()); + }, + "advertiser-filter.kind" => { + request_advertiser_filter_init(&mut request); + request.advertiser_filter.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-filter.object-ids" => { + request_campaign_filter_init(&mut request); + if request.campaign_filter.as_mut().unwrap().object_ids.is_none() { + request.campaign_filter.as_mut().unwrap().object_ids = Some(Default::default()); + } + request.campaign_filter.as_mut().unwrap().object_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "campaign-filter.status" => { + request_campaign_filter_init(&mut request); + request.campaign_filter.as_mut().unwrap().status = Some(value.unwrap_or("").to_string()); + }, + "campaign-filter.kind" => { + request_campaign_filter_init(&mut request); + request.campaign_filter.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "email" => { + request_campaign_filter_init(&mut request); + request.email = Some(value.unwrap_or("").to_string()); + }, + "user-role-id" => { + request_campaign_filter_init(&mut request); + request.user_role_id = Some(value.unwrap_or("").to_string()); + }, + "user-access-type" => { + request_campaign_filter_init(&mut request); + request.user_access_type = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_campaign_filter_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "id" => { + request_campaign_filter_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_campaign_filter_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "advertiser-filter", "campaign-filter", "comments", "email", "id", "kind", "locale", "name", "object-ids", "site-filter", "status", "subaccount-id", "trafficker-type", "user-access-type", "user-role-filter", "user-role-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.account_user_profiles().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _account_user_profiles_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.account_user_profiles().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "user-role-id" => { + call = call.user_role_id(value.unwrap_or("")); + }, + "subaccount-id" => { + call = call.subaccount_id(value.unwrap_or("")); + }, + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "active" => { + call = call.active(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "subaccount-id", "sort-field", "ids", "max-results", "page-token", "user-role-id", "sort-order", "active"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _account_user_profiles_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::AccountUserProfile::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_filter_init(request: &mut api::AccountUserProfile) { + if request.advertiser_filter.is_none() { + request.advertiser_filter = Some(Default::default()); + } + } + + fn request_campaign_filter_init(request: &mut api::AccountUserProfile) { + if request.campaign_filter.is_none() { + request.campaign_filter = Some(Default::default()); + } + } + + fn request_site_filter_init(request: &mut api::AccountUserProfile) { + if request.site_filter.is_none() { + request.site_filter = Some(Default::default()); + } + } + + fn request_user_role_filter_init(request: &mut api::AccountUserProfile) { + if request.user_role_filter.is_none() { + request.user_role_filter = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "user-role-filter.object-ids" => { + request_user_role_filter_init(&mut request); + if request.user_role_filter.as_mut().unwrap().object_ids.is_none() { + request.user_role_filter.as_mut().unwrap().object_ids = Some(Default::default()); + } + request.user_role_filter.as_mut().unwrap().object_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "user-role-filter.status" => { + request_user_role_filter_init(&mut request); + request.user_role_filter.as_mut().unwrap().status = Some(value.unwrap_or("").to_string()); + }, + "user-role-filter.kind" => { + request_user_role_filter_init(&mut request); + request.user_role_filter.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_user_role_filter_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "locale" => { + request_user_role_filter_init(&mut request); + request.locale = Some(value.unwrap_or("").to_string()); + }, + "site-filter.object-ids" => { + request_site_filter_init(&mut request); + if request.site_filter.as_mut().unwrap().object_ids.is_none() { + request.site_filter.as_mut().unwrap().object_ids = Some(Default::default()); + } + request.site_filter.as_mut().unwrap().object_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "site-filter.status" => { + request_site_filter_init(&mut request); + request.site_filter.as_mut().unwrap().status = Some(value.unwrap_or("").to_string()); + }, + "site-filter.kind" => { + request_site_filter_init(&mut request); + request.site_filter.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "comments" => { + request_site_filter_init(&mut request); + request.comments = Some(value.unwrap_or("").to_string()); + }, + "trafficker-type" => { + request_site_filter_init(&mut request); + request.trafficker_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-filter.object-ids" => { + request_advertiser_filter_init(&mut request); + if request.advertiser_filter.as_mut().unwrap().object_ids.is_none() { + request.advertiser_filter.as_mut().unwrap().object_ids = Some(Default::default()); + } + request.advertiser_filter.as_mut().unwrap().object_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "advertiser-filter.status" => { + request_advertiser_filter_init(&mut request); + request.advertiser_filter.as_mut().unwrap().status = Some(value.unwrap_or("").to_string()); + }, + "advertiser-filter.kind" => { + request_advertiser_filter_init(&mut request); + request.advertiser_filter.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-filter.object-ids" => { + request_campaign_filter_init(&mut request); + if request.campaign_filter.as_mut().unwrap().object_ids.is_none() { + request.campaign_filter.as_mut().unwrap().object_ids = Some(Default::default()); + } + request.campaign_filter.as_mut().unwrap().object_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "campaign-filter.status" => { + request_campaign_filter_init(&mut request); + request.campaign_filter.as_mut().unwrap().status = Some(value.unwrap_or("").to_string()); + }, + "campaign-filter.kind" => { + request_campaign_filter_init(&mut request); + request.campaign_filter.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "email" => { + request_campaign_filter_init(&mut request); + request.email = Some(value.unwrap_or("").to_string()); + }, + "user-role-id" => { + request_campaign_filter_init(&mut request); + request.user_role_id = Some(value.unwrap_or("").to_string()); + }, + "user-access-type" => { + request_campaign_filter_init(&mut request); + request.user_access_type = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_campaign_filter_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "id" => { + request_campaign_filter_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_campaign_filter_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "advertiser-filter", "campaign-filter", "comments", "email", "id", "kind", "locale", "name", "object-ids", "site-filter", "status", "subaccount-id", "trafficker-type", "user-access-type", "user-role-filter", "user-role-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.account_user_profiles().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _account_user_profiles_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::AccountUserProfile::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_filter_init(request: &mut api::AccountUserProfile) { + if request.advertiser_filter.is_none() { + request.advertiser_filter = Some(Default::default()); + } + } + + fn request_campaign_filter_init(request: &mut api::AccountUserProfile) { + if request.campaign_filter.is_none() { + request.campaign_filter = Some(Default::default()); + } + } + + fn request_site_filter_init(request: &mut api::AccountUserProfile) { + if request.site_filter.is_none() { + request.site_filter = Some(Default::default()); + } + } + + fn request_user_role_filter_init(request: &mut api::AccountUserProfile) { + if request.user_role_filter.is_none() { + request.user_role_filter = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "user-role-filter.object-ids" => { + request_user_role_filter_init(&mut request); + if request.user_role_filter.as_mut().unwrap().object_ids.is_none() { + request.user_role_filter.as_mut().unwrap().object_ids = Some(Default::default()); + } + request.user_role_filter.as_mut().unwrap().object_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "user-role-filter.status" => { + request_user_role_filter_init(&mut request); + request.user_role_filter.as_mut().unwrap().status = Some(value.unwrap_or("").to_string()); + }, + "user-role-filter.kind" => { + request_user_role_filter_init(&mut request); + request.user_role_filter.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_user_role_filter_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "locale" => { + request_user_role_filter_init(&mut request); + request.locale = Some(value.unwrap_or("").to_string()); + }, + "site-filter.object-ids" => { + request_site_filter_init(&mut request); + if request.site_filter.as_mut().unwrap().object_ids.is_none() { + request.site_filter.as_mut().unwrap().object_ids = Some(Default::default()); + } + request.site_filter.as_mut().unwrap().object_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "site-filter.status" => { + request_site_filter_init(&mut request); + request.site_filter.as_mut().unwrap().status = Some(value.unwrap_or("").to_string()); + }, + "site-filter.kind" => { + request_site_filter_init(&mut request); + request.site_filter.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "comments" => { + request_site_filter_init(&mut request); + request.comments = Some(value.unwrap_or("").to_string()); + }, + "trafficker-type" => { + request_site_filter_init(&mut request); + request.trafficker_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-filter.object-ids" => { + request_advertiser_filter_init(&mut request); + if request.advertiser_filter.as_mut().unwrap().object_ids.is_none() { + request.advertiser_filter.as_mut().unwrap().object_ids = Some(Default::default()); + } + request.advertiser_filter.as_mut().unwrap().object_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "advertiser-filter.status" => { + request_advertiser_filter_init(&mut request); + request.advertiser_filter.as_mut().unwrap().status = Some(value.unwrap_or("").to_string()); + }, + "advertiser-filter.kind" => { + request_advertiser_filter_init(&mut request); + request.advertiser_filter.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-filter.object-ids" => { + request_campaign_filter_init(&mut request); + if request.campaign_filter.as_mut().unwrap().object_ids.is_none() { + request.campaign_filter.as_mut().unwrap().object_ids = Some(Default::default()); + } + request.campaign_filter.as_mut().unwrap().object_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "campaign-filter.status" => { + request_campaign_filter_init(&mut request); + request.campaign_filter.as_mut().unwrap().status = Some(value.unwrap_or("").to_string()); + }, + "campaign-filter.kind" => { + request_campaign_filter_init(&mut request); + request.campaign_filter.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "email" => { + request_campaign_filter_init(&mut request); + request.email = Some(value.unwrap_or("").to_string()); + }, + "user-role-id" => { + request_campaign_filter_init(&mut request); + request.user_role_id = Some(value.unwrap_or("").to_string()); + }, + "user-access-type" => { + request_campaign_filter_init(&mut request); + request.user_access_type = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_campaign_filter_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "id" => { + request_campaign_filter_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_campaign_filter_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "advertiser-filter", "campaign-filter", "comments", "email", "id", "kind", "locale", "name", "object-ids", "site-filter", "status", "subaccount-id", "trafficker-type", "user-access-type", "user-role-filter", "user-role-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.account_user_profiles().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _accounts_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _accounts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "active" => { + call = call.active(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "sort-field", "ids", "max-results", "page-token", "sort-order", "active"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _accounts_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Account::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_reports_configuration_init(request: &mut api::Account) { + if request.reports_configuration.is_none() { + request.reports_configuration = Some(Default::default()); + } + } + + fn request_reports_configuration_lookback_configuration_init(request: &mut api::Account) { + request_reports_configuration_init(request); + if request.reports_configuration.as_mut().unwrap().lookback_configuration.is_none() { + request.reports_configuration.as_mut().unwrap().lookback_configuration = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "teaser-size-limit" => { + request.teaser_size_limit = Some(value.unwrap_or("").to_string()); + }, + "active-view-opt-out" => { + request.active_view_opt_out = Some(arg_from_str(value.unwrap_or("false"), err, "active-view-opt-out", "boolean")); + }, + "description" => { + request.description = Some(value.unwrap_or("").to_string()); + }, + "maximum-image-size" => { + request.maximum_image_size = Some(value.unwrap_or("").to_string()); + }, + "locale" => { + request.locale = Some(value.unwrap_or("").to_string()); + }, + "default-creative-size-id" => { + request.default_creative_size_id = Some(value.unwrap_or("").to_string()); + }, + "account-permission-ids" => { + if request.account_permission_ids.is_none() { + request.account_permission_ids = Some(Default::default()); + } + request.account_permission_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "account-profile" => { + request.account_profile = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "nielsen-ocr-enabled" => { + request.nielsen_ocr_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "nielsen-ocr-enabled", "boolean")); + }, + "reports-configuration.report-generation-time-zone-id" => { + request_reports_configuration_init(&mut request); + request.reports_configuration.as_mut().unwrap().report_generation_time_zone_id = Some(value.unwrap_or("").to_string()); + }, + "reports-configuration.exposure-to-conversion-enabled" => { + request_reports_configuration_init(&mut request); + request.reports_configuration.as_mut().unwrap().exposure_to_conversion_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "reports-configuration.exposure-to-conversion-enabled", "boolean")); + }, + "reports-configuration.lookback-configuration.click-duration" => { + request_reports_configuration_lookback_configuration_init(&mut request); + request.reports_configuration.as_mut().unwrap().lookback_configuration.as_mut().unwrap().click_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "reports-configuration.lookback-configuration.click-duration", "integer")); + }, + "reports-configuration.lookback-configuration.post-impression-activities-duration" => { + request_reports_configuration_lookback_configuration_init(&mut request); + request.reports_configuration.as_mut().unwrap().lookback_configuration.as_mut().unwrap().post_impression_activities_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "reports-configuration.lookback-configuration.post-impression-activities-duration", "integer")); + }, + "currency-id" => { + request_reports_configuration_init(&mut request); + request.currency_id = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_reports_configuration_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "comscore-vce-enabled" => { + request_reports_configuration_init(&mut request); + request.comscore_vce_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "comscore-vce-enabled", "boolean")); + }, + "active-ads-limit-tier" => { + request_reports_configuration_init(&mut request); + request.active_ads_limit_tier = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_reports_configuration_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "country-id" => { + request_reports_configuration_init(&mut request); + request.country_id = Some(value.unwrap_or("").to_string()); + }, + "available-permission-ids" => { + request_reports_configuration_init(&mut request); + if request.available_permission_ids.is_none() { + request.available_permission_ids = Some(Default::default()); + } + request.available_permission_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-permission-ids", "account-profile", "active", "active-ads-limit-tier", "active-view-opt-out", "available-permission-ids", "click-duration", "comscore-vce-enabled", "country-id", "currency-id", "default-creative-size-id", "description", "exposure-to-conversion-enabled", "id", "kind", "locale", "lookback-configuration", "maximum-image-size", "name", "nielsen-ocr-enabled", "post-impression-activities-duration", "report-generation-time-zone-id", "reports-configuration", "teaser-size-limit"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.accounts().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _accounts_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Account::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_reports_configuration_init(request: &mut api::Account) { + if request.reports_configuration.is_none() { + request.reports_configuration = Some(Default::default()); + } + } + + fn request_reports_configuration_lookback_configuration_init(request: &mut api::Account) { + request_reports_configuration_init(request); + if request.reports_configuration.as_mut().unwrap().lookback_configuration.is_none() { + request.reports_configuration.as_mut().unwrap().lookback_configuration = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "teaser-size-limit" => { + request.teaser_size_limit = Some(value.unwrap_or("").to_string()); + }, + "active-view-opt-out" => { + request.active_view_opt_out = Some(arg_from_str(value.unwrap_or("false"), err, "active-view-opt-out", "boolean")); + }, + "description" => { + request.description = Some(value.unwrap_or("").to_string()); + }, + "maximum-image-size" => { + request.maximum_image_size = Some(value.unwrap_or("").to_string()); + }, + "locale" => { + request.locale = Some(value.unwrap_or("").to_string()); + }, + "default-creative-size-id" => { + request.default_creative_size_id = Some(value.unwrap_or("").to_string()); + }, + "account-permission-ids" => { + if request.account_permission_ids.is_none() { + request.account_permission_ids = Some(Default::default()); + } + request.account_permission_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "account-profile" => { + request.account_profile = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "nielsen-ocr-enabled" => { + request.nielsen_ocr_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "nielsen-ocr-enabled", "boolean")); + }, + "reports-configuration.report-generation-time-zone-id" => { + request_reports_configuration_init(&mut request); + request.reports_configuration.as_mut().unwrap().report_generation_time_zone_id = Some(value.unwrap_or("").to_string()); + }, + "reports-configuration.exposure-to-conversion-enabled" => { + request_reports_configuration_init(&mut request); + request.reports_configuration.as_mut().unwrap().exposure_to_conversion_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "reports-configuration.exposure-to-conversion-enabled", "boolean")); + }, + "reports-configuration.lookback-configuration.click-duration" => { + request_reports_configuration_lookback_configuration_init(&mut request); + request.reports_configuration.as_mut().unwrap().lookback_configuration.as_mut().unwrap().click_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "reports-configuration.lookback-configuration.click-duration", "integer")); + }, + "reports-configuration.lookback-configuration.post-impression-activities-duration" => { + request_reports_configuration_lookback_configuration_init(&mut request); + request.reports_configuration.as_mut().unwrap().lookback_configuration.as_mut().unwrap().post_impression_activities_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "reports-configuration.lookback-configuration.post-impression-activities-duration", "integer")); + }, + "currency-id" => { + request_reports_configuration_init(&mut request); + request.currency_id = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_reports_configuration_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "comscore-vce-enabled" => { + request_reports_configuration_init(&mut request); + request.comscore_vce_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "comscore-vce-enabled", "boolean")); + }, + "active-ads-limit-tier" => { + request_reports_configuration_init(&mut request); + request.active_ads_limit_tier = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_reports_configuration_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "country-id" => { + request_reports_configuration_init(&mut request); + request.country_id = Some(value.unwrap_or("").to_string()); + }, + "available-permission-ids" => { + request_reports_configuration_init(&mut request); + if request.available_permission_ids.is_none() { + request.available_permission_ids = Some(Default::default()); + } + request.available_permission_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-permission-ids", "account-profile", "active", "active-ads-limit-tier", "active-view-opt-out", "available-permission-ids", "click-duration", "comscore-vce-enabled", "country-id", "currency-id", "default-creative-size-id", "description", "exposure-to-conversion-enabled", "id", "kind", "locale", "lookback-configuration", "maximum-image-size", "name", "nielsen-ocr-enabled", "post-impression-activities-duration", "report-generation-time-zone-id", "reports-configuration", "teaser-size-limit"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.accounts().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _ads_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.ads().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _ads_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Ad::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::Ad) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_campaign_id_dimension_value_init(request: &mut api::Ad) { + if request.campaign_id_dimension_value.is_none() { + request.campaign_id_dimension_value = Some(Default::default()); + } + } + + fn request_click_through_url_init(request: &mut api::Ad) { + if request.click_through_url.is_none() { + request.click_through_url = Some(Default::default()); + } + } + + fn request_click_through_url_suffix_properties_init(request: &mut api::Ad) { + if request.click_through_url_suffix_properties.is_none() { + request.click_through_url_suffix_properties = Some(Default::default()); + } + } + + fn request_create_info_init(request: &mut api::Ad) { + if request.create_info.is_none() { + request.create_info = Some(Default::default()); + } + } + + fn request_creative_rotation_init(request: &mut api::Ad) { + if request.creative_rotation.is_none() { + request.creative_rotation = Some(Default::default()); + } + } + + fn request_day_part_targeting_init(request: &mut api::Ad) { + if request.day_part_targeting.is_none() { + request.day_part_targeting = Some(Default::default()); + } + } + + fn request_default_click_through_event_tag_properties_init(request: &mut api::Ad) { + if request.default_click_through_event_tag_properties.is_none() { + request.default_click_through_event_tag_properties = Some(Default::default()); + } + } + + fn request_delivery_schedule_frequency_cap_init(request: &mut api::Ad) { + request_delivery_schedule_init(request); + if request.delivery_schedule.as_mut().unwrap().frequency_cap.is_none() { + request.delivery_schedule.as_mut().unwrap().frequency_cap = Some(Default::default()); + } + } + + fn request_delivery_schedule_init(request: &mut api::Ad) { + if request.delivery_schedule.is_none() { + request.delivery_schedule = Some(Default::default()); + } + } + + fn request_geo_targeting_init(request: &mut api::Ad) { + if request.geo_targeting.is_none() { + request.geo_targeting = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Ad) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_key_value_targeting_expression_init(request: &mut api::Ad) { + if request.key_value_targeting_expression.is_none() { + request.key_value_targeting_expression = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::Ad) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_remarketing_list_expression_init(request: &mut api::Ad) { + if request.remarketing_list_expression.is_none() { + request.remarketing_list_expression = Some(Default::default()); + } + } + + fn request_size_init(request: &mut api::Ad) { + if request.size.is_none() { + request.size = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "click-through-url-suffix-properties.click-through-url-suffix" => { + request_click_through_url_suffix_properties_init(&mut request); + request.click_through_url_suffix_properties.as_mut().unwrap().click_through_url_suffix = Some(value.unwrap_or("").to_string()); + }, + "click-through-url-suffix-properties.override-inherited-suffix" => { + request_click_through_url_suffix_properties_init(&mut request); + request.click_through_url_suffix_properties.as_mut().unwrap().override_inherited_suffix = Some(arg_from_str(value.unwrap_or("false"), err, "click-through-url-suffix-properties.override-inherited-suffix", "boolean")); + }, + "campaign-id" => { + request_click_through_url_suffix_properties_init(&mut request); + request.campaign_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request_click_through_url_suffix_properties_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "geo-targeting.exclude-countries" => { + request_geo_targeting_init(&mut request); + request.geo_targeting.as_mut().unwrap().exclude_countries = Some(arg_from_str(value.unwrap_or("false"), err, "geo-targeting.exclude-countries", "boolean")); + }, + "delivery-schedule.priority" => { + request_delivery_schedule_init(&mut request); + request.delivery_schedule.as_mut().unwrap().priority = Some(value.unwrap_or("").to_string()); + }, + "delivery-schedule.hard-cutoff" => { + request_delivery_schedule_init(&mut request); + request.delivery_schedule.as_mut().unwrap().hard_cutoff = Some(arg_from_str(value.unwrap_or("false"), err, "delivery-schedule.hard-cutoff", "boolean")); + }, + "delivery-schedule.frequency-cap.duration" => { + request_delivery_schedule_frequency_cap_init(&mut request); + request.delivery_schedule.as_mut().unwrap().frequency_cap.as_mut().unwrap().duration = Some(value.unwrap_or("").to_string()); + }, + "delivery-schedule.frequency-cap.impressions" => { + request_delivery_schedule_frequency_cap_init(&mut request); + request.delivery_schedule.as_mut().unwrap().frequency_cap.as_mut().unwrap().impressions = Some(value.unwrap_or("").to_string()); + }, + "delivery-schedule.impression-ratio" => { + request_delivery_schedule_frequency_cap_init(&mut request); + request.delivery_schedule.as_mut().unwrap().impression_ratio = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "remarketing-list-expression.expression" => { + request_remarketing_list_expression_init(&mut request); + request.remarketing_list_expression.as_mut().unwrap().expression = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_remarketing_list_expression_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "archived" => { + request_remarketing_list_expression_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "creative-rotation.weight-calculation-strategy" => { + request_creative_rotation_init(&mut request); + request.creative_rotation.as_mut().unwrap().weight_calculation_strategy = Some(value.unwrap_or("").to_string()); + }, + "creative-rotation.creative-optimization-configuration-id" => { + request_creative_rotation_init(&mut request); + request.creative_rotation.as_mut().unwrap().creative_optimization_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "creative-rotation.type" => { + request_creative_rotation_init(&mut request); + request.creative_rotation.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); + }, + "click-through-url.landing-page-id" => { + request_click_through_url_init(&mut request); + request.click_through_url.as_mut().unwrap().landing_page_id = Some(value.unwrap_or("").to_string()); + }, + "click-through-url.custom-click-through-url" => { + request_click_through_url_init(&mut request); + request.click_through_url.as_mut().unwrap().custom_click_through_url = Some(value.unwrap_or("").to_string()); + }, + "click-through-url.default-landing-page" => { + request_click_through_url_init(&mut request); + request.click_through_url.as_mut().unwrap().default_landing_page = Some(arg_from_str(value.unwrap_or("false"), err, "click-through-url.default-landing-page", "boolean")); + }, + "comments" => { + request_click_through_url_init(&mut request); + request.comments = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.width" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().width = Some(arg_from_str(value.unwrap_or("-0"), err, "size.width", "integer")); + }, + "size.kind" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "size.iab" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().iab = Some(arg_from_str(value.unwrap_or("false"), err, "size.iab", "boolean")); + }, + "size.id" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.height" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().height = Some(arg_from_str(value.unwrap_or("-0"), err, "size.height", "integer")); + }, + "type" => { + request_size_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "ssl-required" => { + request_size_init(&mut request); + request.ssl_required = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-required", "boolean")); + }, + "audience-segment-id" => { + request_size_init(&mut request); + request.audience_segment_id = Some(value.unwrap_or("").to_string()); + }, + "key-value-targeting-expression.expression" => { + request_key_value_targeting_expression_init(&mut request); + request.key_value_targeting_expression.as_mut().unwrap().expression = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.value" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.dimension-name" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.etag" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.match-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.id" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "default-click-through-event-tag-properties.override-inherited-event-tag" => { + request_default_click_through_event_tag_properties_init(&mut request); + request.default_click_through_event_tag_properties.as_mut().unwrap().override_inherited_event_tag = Some(arg_from_str(value.unwrap_or("false"), err, "default-click-through-event-tag-properties.override-inherited-event-tag", "boolean")); + }, + "default-click-through-event-tag-properties.default-click-through-event-tag-id" => { + request_default_click_through_event_tag_properties_init(&mut request); + request.default_click_through_event_tag_properties.as_mut().unwrap().default_click_through_event_tag_id = Some(value.unwrap_or("").to_string()); + }, + "create-info.time" => { + request_create_info_init(&mut request); + request.create_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "start-time" => { + request_create_info_init(&mut request); + request.start_time = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_create_info_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "compatibility" => { + request_create_info_init(&mut request); + request.compatibility = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_create_info_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_create_info_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_create_info_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "day-part-targeting.user-local-time" => { + request_day_part_targeting_init(&mut request); + request.day_part_targeting.as_mut().unwrap().user_local_time = Some(arg_from_str(value.unwrap_or("false"), err, "day-part-targeting.user-local-time", "boolean")); + }, + "day-part-targeting.hours-of-day" => { + request_day_part_targeting_init(&mut request); + if request.day_part_targeting.as_mut().unwrap().hours_of_day.is_none() { + request.day_part_targeting.as_mut().unwrap().hours_of_day = Some(Default::default()); + } + request.day_part_targeting.as_mut().unwrap().hours_of_day.as_mut().unwrap().push(arg_from_str(value.unwrap_or("-0"), err, "day-part-targeting.hours-of-day", "integer")); + }, + "day-part-targeting.days-of-week" => { + request_day_part_targeting_init(&mut request); + if request.day_part_targeting.as_mut().unwrap().days_of_week.is_none() { + request.day_part_targeting.as_mut().unwrap().days_of_week = Some(Default::default()); + } + request.day_part_targeting.as_mut().unwrap().days_of_week.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "ssl-compliant" => { + request_last_modified_info_init(&mut request); + request.ssl_compliant = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-compliant", "boolean")); + }, + "end-time" => { + request_last_modified_info_init(&mut request); + request.end_time = Some(value.unwrap_or("").to_string()); + }, + "dynamic-click-tracker" => { + request_last_modified_info_init(&mut request); + request.dynamic_click_tracker = Some(arg_from_str(value.unwrap_or("false"), err, "dynamic-click-tracker", "boolean")); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "advertiser-id", "advertiser-id-dimension-value", "archived", "audience-segment-id", "campaign-id", "campaign-id-dimension-value", "click-through-url", "click-through-url-suffix", "click-through-url-suffix-properties", "comments", "compatibility", "create-info", "creative-optimization-configuration-id", "creative-rotation", "custom-click-through-url", "day-part-targeting", "days-of-week", "default-click-through-event-tag-id", "default-click-through-event-tag-properties", "default-landing-page", "delivery-schedule", "dimension-name", "duration", "dynamic-click-tracker", "end-time", "etag", "exclude-countries", "expression", "frequency-cap", "geo-targeting", "hard-cutoff", "height", "hours-of-day", "iab", "id", "id-dimension-value", "impression-ratio", "impressions", "key-value-targeting-expression", "kind", "landing-page-id", "last-modified-info", "match-type", "name", "override-inherited-event-tag", "override-inherited-suffix", "priority", "remarketing-list-expression", "size", "ssl-compliant", "ssl-required", "start-time", "subaccount-id", "time", "type", "user-local-time", "value", "weight-calculation-strategy", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.ads().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _ads_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.ads().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "type" => { + call = call.add_type(value.unwrap_or("")); + }, + "ssl-required" => { + call = call.ssl_required(arg_from_str(value.unwrap_or("false"), err, "ssl-required", "boolean")); + }, + "ssl-compliant" => { + call = call.ssl_compliant(arg_from_str(value.unwrap_or("false"), err, "ssl-compliant", "boolean")); + }, + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "size-ids" => { + call = call.add_size_ids(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "remarketing-list-ids" => { + call = call.add_remarketing_list_ids(value.unwrap_or("")); + }, + "placement-ids" => { + call = call.add_placement_ids(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "overridden-event-tag-id" => { + call = call.overridden_event_tag_id(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "landing-page-ids" => { + call = call.add_landing_page_ids(value.unwrap_or("")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "dynamic-click-tracker" => { + call = call.dynamic_click_tracker(arg_from_str(value.unwrap_or("false"), err, "dynamic-click-tracker", "boolean")); + }, + "creative-type" => { + call = call.creative_type(value.unwrap_or("")); + }, + "creative-optimization-configuration-ids" => { + call = call.add_creative_optimization_configuration_ids(value.unwrap_or("")); + }, + "creative-ids" => { + call = call.add_creative_ids(value.unwrap_or("")); + }, + "compatibility" => { + call = call.compatibility(value.unwrap_or("")); + }, + "campaign-ids" => { + call = call.add_campaign_ids(value.unwrap_or("")); + }, + "audience-segment-ids" => { + call = call.add_audience_segment_ids(value.unwrap_or("")); + }, + "archived" => { + call = call.archived(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "advertiser-id" => { + call = call.advertiser_id(value.unwrap_or("")); + }, + "active" => { + call = call.active(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["landing-page-ids", "overridden-event-tag-id", "campaign-ids", "archived", "creative-optimization-configuration-ids", "ssl-compliant", "size-ids", "page-token", "sort-order", "type", "ssl-required", "creative-ids", "max-results", "creative-type", "placement-ids", "active", "compatibility", "advertiser-id", "search-string", "sort-field", "audience-segment-ids", "ids", "remarketing-list-ids", "dynamic-click-tracker"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _ads_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Ad::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::Ad) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_campaign_id_dimension_value_init(request: &mut api::Ad) { + if request.campaign_id_dimension_value.is_none() { + request.campaign_id_dimension_value = Some(Default::default()); + } + } + + fn request_click_through_url_init(request: &mut api::Ad) { + if request.click_through_url.is_none() { + request.click_through_url = Some(Default::default()); + } + } + + fn request_click_through_url_suffix_properties_init(request: &mut api::Ad) { + if request.click_through_url_suffix_properties.is_none() { + request.click_through_url_suffix_properties = Some(Default::default()); + } + } + + fn request_create_info_init(request: &mut api::Ad) { + if request.create_info.is_none() { + request.create_info = Some(Default::default()); + } + } + + fn request_creative_rotation_init(request: &mut api::Ad) { + if request.creative_rotation.is_none() { + request.creative_rotation = Some(Default::default()); + } + } + + fn request_day_part_targeting_init(request: &mut api::Ad) { + if request.day_part_targeting.is_none() { + request.day_part_targeting = Some(Default::default()); + } + } + + fn request_default_click_through_event_tag_properties_init(request: &mut api::Ad) { + if request.default_click_through_event_tag_properties.is_none() { + request.default_click_through_event_tag_properties = Some(Default::default()); + } + } + + fn request_delivery_schedule_frequency_cap_init(request: &mut api::Ad) { + request_delivery_schedule_init(request); + if request.delivery_schedule.as_mut().unwrap().frequency_cap.is_none() { + request.delivery_schedule.as_mut().unwrap().frequency_cap = Some(Default::default()); + } + } + + fn request_delivery_schedule_init(request: &mut api::Ad) { + if request.delivery_schedule.is_none() { + request.delivery_schedule = Some(Default::default()); + } + } + + fn request_geo_targeting_init(request: &mut api::Ad) { + if request.geo_targeting.is_none() { + request.geo_targeting = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Ad) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_key_value_targeting_expression_init(request: &mut api::Ad) { + if request.key_value_targeting_expression.is_none() { + request.key_value_targeting_expression = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::Ad) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_remarketing_list_expression_init(request: &mut api::Ad) { + if request.remarketing_list_expression.is_none() { + request.remarketing_list_expression = Some(Default::default()); + } + } + + fn request_size_init(request: &mut api::Ad) { + if request.size.is_none() { + request.size = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "click-through-url-suffix-properties.click-through-url-suffix" => { + request_click_through_url_suffix_properties_init(&mut request); + request.click_through_url_suffix_properties.as_mut().unwrap().click_through_url_suffix = Some(value.unwrap_or("").to_string()); + }, + "click-through-url-suffix-properties.override-inherited-suffix" => { + request_click_through_url_suffix_properties_init(&mut request); + request.click_through_url_suffix_properties.as_mut().unwrap().override_inherited_suffix = Some(arg_from_str(value.unwrap_or("false"), err, "click-through-url-suffix-properties.override-inherited-suffix", "boolean")); + }, + "campaign-id" => { + request_click_through_url_suffix_properties_init(&mut request); + request.campaign_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request_click_through_url_suffix_properties_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "geo-targeting.exclude-countries" => { + request_geo_targeting_init(&mut request); + request.geo_targeting.as_mut().unwrap().exclude_countries = Some(arg_from_str(value.unwrap_or("false"), err, "geo-targeting.exclude-countries", "boolean")); + }, + "delivery-schedule.priority" => { + request_delivery_schedule_init(&mut request); + request.delivery_schedule.as_mut().unwrap().priority = Some(value.unwrap_or("").to_string()); + }, + "delivery-schedule.hard-cutoff" => { + request_delivery_schedule_init(&mut request); + request.delivery_schedule.as_mut().unwrap().hard_cutoff = Some(arg_from_str(value.unwrap_or("false"), err, "delivery-schedule.hard-cutoff", "boolean")); + }, + "delivery-schedule.frequency-cap.duration" => { + request_delivery_schedule_frequency_cap_init(&mut request); + request.delivery_schedule.as_mut().unwrap().frequency_cap.as_mut().unwrap().duration = Some(value.unwrap_or("").to_string()); + }, + "delivery-schedule.frequency-cap.impressions" => { + request_delivery_schedule_frequency_cap_init(&mut request); + request.delivery_schedule.as_mut().unwrap().frequency_cap.as_mut().unwrap().impressions = Some(value.unwrap_or("").to_string()); + }, + "delivery-schedule.impression-ratio" => { + request_delivery_schedule_frequency_cap_init(&mut request); + request.delivery_schedule.as_mut().unwrap().impression_ratio = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "remarketing-list-expression.expression" => { + request_remarketing_list_expression_init(&mut request); + request.remarketing_list_expression.as_mut().unwrap().expression = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_remarketing_list_expression_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "archived" => { + request_remarketing_list_expression_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "creative-rotation.weight-calculation-strategy" => { + request_creative_rotation_init(&mut request); + request.creative_rotation.as_mut().unwrap().weight_calculation_strategy = Some(value.unwrap_or("").to_string()); + }, + "creative-rotation.creative-optimization-configuration-id" => { + request_creative_rotation_init(&mut request); + request.creative_rotation.as_mut().unwrap().creative_optimization_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "creative-rotation.type" => { + request_creative_rotation_init(&mut request); + request.creative_rotation.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); + }, + "click-through-url.landing-page-id" => { + request_click_through_url_init(&mut request); + request.click_through_url.as_mut().unwrap().landing_page_id = Some(value.unwrap_or("").to_string()); + }, + "click-through-url.custom-click-through-url" => { + request_click_through_url_init(&mut request); + request.click_through_url.as_mut().unwrap().custom_click_through_url = Some(value.unwrap_or("").to_string()); + }, + "click-through-url.default-landing-page" => { + request_click_through_url_init(&mut request); + request.click_through_url.as_mut().unwrap().default_landing_page = Some(arg_from_str(value.unwrap_or("false"), err, "click-through-url.default-landing-page", "boolean")); + }, + "comments" => { + request_click_through_url_init(&mut request); + request.comments = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.width" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().width = Some(arg_from_str(value.unwrap_or("-0"), err, "size.width", "integer")); + }, + "size.kind" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "size.iab" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().iab = Some(arg_from_str(value.unwrap_or("false"), err, "size.iab", "boolean")); + }, + "size.id" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.height" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().height = Some(arg_from_str(value.unwrap_or("-0"), err, "size.height", "integer")); + }, + "type" => { + request_size_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "ssl-required" => { + request_size_init(&mut request); + request.ssl_required = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-required", "boolean")); + }, + "audience-segment-id" => { + request_size_init(&mut request); + request.audience_segment_id = Some(value.unwrap_or("").to_string()); + }, + "key-value-targeting-expression.expression" => { + request_key_value_targeting_expression_init(&mut request); + request.key_value_targeting_expression.as_mut().unwrap().expression = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.value" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.dimension-name" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.etag" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.match-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.id" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "default-click-through-event-tag-properties.override-inherited-event-tag" => { + request_default_click_through_event_tag_properties_init(&mut request); + request.default_click_through_event_tag_properties.as_mut().unwrap().override_inherited_event_tag = Some(arg_from_str(value.unwrap_or("false"), err, "default-click-through-event-tag-properties.override-inherited-event-tag", "boolean")); + }, + "default-click-through-event-tag-properties.default-click-through-event-tag-id" => { + request_default_click_through_event_tag_properties_init(&mut request); + request.default_click_through_event_tag_properties.as_mut().unwrap().default_click_through_event_tag_id = Some(value.unwrap_or("").to_string()); + }, + "create-info.time" => { + request_create_info_init(&mut request); + request.create_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "start-time" => { + request_create_info_init(&mut request); + request.start_time = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_create_info_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "compatibility" => { + request_create_info_init(&mut request); + request.compatibility = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_create_info_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_create_info_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_create_info_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "day-part-targeting.user-local-time" => { + request_day_part_targeting_init(&mut request); + request.day_part_targeting.as_mut().unwrap().user_local_time = Some(arg_from_str(value.unwrap_or("false"), err, "day-part-targeting.user-local-time", "boolean")); + }, + "day-part-targeting.hours-of-day" => { + request_day_part_targeting_init(&mut request); + if request.day_part_targeting.as_mut().unwrap().hours_of_day.is_none() { + request.day_part_targeting.as_mut().unwrap().hours_of_day = Some(Default::default()); + } + request.day_part_targeting.as_mut().unwrap().hours_of_day.as_mut().unwrap().push(arg_from_str(value.unwrap_or("-0"), err, "day-part-targeting.hours-of-day", "integer")); + }, + "day-part-targeting.days-of-week" => { + request_day_part_targeting_init(&mut request); + if request.day_part_targeting.as_mut().unwrap().days_of_week.is_none() { + request.day_part_targeting.as_mut().unwrap().days_of_week = Some(Default::default()); + } + request.day_part_targeting.as_mut().unwrap().days_of_week.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "ssl-compliant" => { + request_last_modified_info_init(&mut request); + request.ssl_compliant = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-compliant", "boolean")); + }, + "end-time" => { + request_last_modified_info_init(&mut request); + request.end_time = Some(value.unwrap_or("").to_string()); + }, + "dynamic-click-tracker" => { + request_last_modified_info_init(&mut request); + request.dynamic_click_tracker = Some(arg_from_str(value.unwrap_or("false"), err, "dynamic-click-tracker", "boolean")); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "advertiser-id", "advertiser-id-dimension-value", "archived", "audience-segment-id", "campaign-id", "campaign-id-dimension-value", "click-through-url", "click-through-url-suffix", "click-through-url-suffix-properties", "comments", "compatibility", "create-info", "creative-optimization-configuration-id", "creative-rotation", "custom-click-through-url", "day-part-targeting", "days-of-week", "default-click-through-event-tag-id", "default-click-through-event-tag-properties", "default-landing-page", "delivery-schedule", "dimension-name", "duration", "dynamic-click-tracker", "end-time", "etag", "exclude-countries", "expression", "frequency-cap", "geo-targeting", "hard-cutoff", "height", "hours-of-day", "iab", "id", "id-dimension-value", "impression-ratio", "impressions", "key-value-targeting-expression", "kind", "landing-page-id", "last-modified-info", "match-type", "name", "override-inherited-event-tag", "override-inherited-suffix", "priority", "remarketing-list-expression", "size", "ssl-compliant", "ssl-required", "start-time", "subaccount-id", "time", "type", "user-local-time", "value", "weight-calculation-strategy", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.ads().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _ads_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Ad::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::Ad) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_campaign_id_dimension_value_init(request: &mut api::Ad) { + if request.campaign_id_dimension_value.is_none() { + request.campaign_id_dimension_value = Some(Default::default()); + } + } + + fn request_click_through_url_init(request: &mut api::Ad) { + if request.click_through_url.is_none() { + request.click_through_url = Some(Default::default()); + } + } + + fn request_click_through_url_suffix_properties_init(request: &mut api::Ad) { + if request.click_through_url_suffix_properties.is_none() { + request.click_through_url_suffix_properties = Some(Default::default()); + } + } + + fn request_create_info_init(request: &mut api::Ad) { + if request.create_info.is_none() { + request.create_info = Some(Default::default()); + } + } + + fn request_creative_rotation_init(request: &mut api::Ad) { + if request.creative_rotation.is_none() { + request.creative_rotation = Some(Default::default()); + } + } + + fn request_day_part_targeting_init(request: &mut api::Ad) { + if request.day_part_targeting.is_none() { + request.day_part_targeting = Some(Default::default()); + } + } + + fn request_default_click_through_event_tag_properties_init(request: &mut api::Ad) { + if request.default_click_through_event_tag_properties.is_none() { + request.default_click_through_event_tag_properties = Some(Default::default()); + } + } + + fn request_delivery_schedule_frequency_cap_init(request: &mut api::Ad) { + request_delivery_schedule_init(request); + if request.delivery_schedule.as_mut().unwrap().frequency_cap.is_none() { + request.delivery_schedule.as_mut().unwrap().frequency_cap = Some(Default::default()); + } + } + + fn request_delivery_schedule_init(request: &mut api::Ad) { + if request.delivery_schedule.is_none() { + request.delivery_schedule = Some(Default::default()); + } + } + + fn request_geo_targeting_init(request: &mut api::Ad) { + if request.geo_targeting.is_none() { + request.geo_targeting = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Ad) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_key_value_targeting_expression_init(request: &mut api::Ad) { + if request.key_value_targeting_expression.is_none() { + request.key_value_targeting_expression = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::Ad) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_remarketing_list_expression_init(request: &mut api::Ad) { + if request.remarketing_list_expression.is_none() { + request.remarketing_list_expression = Some(Default::default()); + } + } + + fn request_size_init(request: &mut api::Ad) { + if request.size.is_none() { + request.size = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "click-through-url-suffix-properties.click-through-url-suffix" => { + request_click_through_url_suffix_properties_init(&mut request); + request.click_through_url_suffix_properties.as_mut().unwrap().click_through_url_suffix = Some(value.unwrap_or("").to_string()); + }, + "click-through-url-suffix-properties.override-inherited-suffix" => { + request_click_through_url_suffix_properties_init(&mut request); + request.click_through_url_suffix_properties.as_mut().unwrap().override_inherited_suffix = Some(arg_from_str(value.unwrap_or("false"), err, "click-through-url-suffix-properties.override-inherited-suffix", "boolean")); + }, + "campaign-id" => { + request_click_through_url_suffix_properties_init(&mut request); + request.campaign_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request_click_through_url_suffix_properties_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "geo-targeting.exclude-countries" => { + request_geo_targeting_init(&mut request); + request.geo_targeting.as_mut().unwrap().exclude_countries = Some(arg_from_str(value.unwrap_or("false"), err, "geo-targeting.exclude-countries", "boolean")); + }, + "delivery-schedule.priority" => { + request_delivery_schedule_init(&mut request); + request.delivery_schedule.as_mut().unwrap().priority = Some(value.unwrap_or("").to_string()); + }, + "delivery-schedule.hard-cutoff" => { + request_delivery_schedule_init(&mut request); + request.delivery_schedule.as_mut().unwrap().hard_cutoff = Some(arg_from_str(value.unwrap_or("false"), err, "delivery-schedule.hard-cutoff", "boolean")); + }, + "delivery-schedule.frequency-cap.duration" => { + request_delivery_schedule_frequency_cap_init(&mut request); + request.delivery_schedule.as_mut().unwrap().frequency_cap.as_mut().unwrap().duration = Some(value.unwrap_or("").to_string()); + }, + "delivery-schedule.frequency-cap.impressions" => { + request_delivery_schedule_frequency_cap_init(&mut request); + request.delivery_schedule.as_mut().unwrap().frequency_cap.as_mut().unwrap().impressions = Some(value.unwrap_or("").to_string()); + }, + "delivery-schedule.impression-ratio" => { + request_delivery_schedule_frequency_cap_init(&mut request); + request.delivery_schedule.as_mut().unwrap().impression_ratio = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "remarketing-list-expression.expression" => { + request_remarketing_list_expression_init(&mut request); + request.remarketing_list_expression.as_mut().unwrap().expression = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_remarketing_list_expression_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "archived" => { + request_remarketing_list_expression_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "creative-rotation.weight-calculation-strategy" => { + request_creative_rotation_init(&mut request); + request.creative_rotation.as_mut().unwrap().weight_calculation_strategy = Some(value.unwrap_or("").to_string()); + }, + "creative-rotation.creative-optimization-configuration-id" => { + request_creative_rotation_init(&mut request); + request.creative_rotation.as_mut().unwrap().creative_optimization_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "creative-rotation.type" => { + request_creative_rotation_init(&mut request); + request.creative_rotation.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); + }, + "click-through-url.landing-page-id" => { + request_click_through_url_init(&mut request); + request.click_through_url.as_mut().unwrap().landing_page_id = Some(value.unwrap_or("").to_string()); + }, + "click-through-url.custom-click-through-url" => { + request_click_through_url_init(&mut request); + request.click_through_url.as_mut().unwrap().custom_click_through_url = Some(value.unwrap_or("").to_string()); + }, + "click-through-url.default-landing-page" => { + request_click_through_url_init(&mut request); + request.click_through_url.as_mut().unwrap().default_landing_page = Some(arg_from_str(value.unwrap_or("false"), err, "click-through-url.default-landing-page", "boolean")); + }, + "comments" => { + request_click_through_url_init(&mut request); + request.comments = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.width" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().width = Some(arg_from_str(value.unwrap_or("-0"), err, "size.width", "integer")); + }, + "size.kind" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "size.iab" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().iab = Some(arg_from_str(value.unwrap_or("false"), err, "size.iab", "boolean")); + }, + "size.id" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.height" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().height = Some(arg_from_str(value.unwrap_or("-0"), err, "size.height", "integer")); + }, + "type" => { + request_size_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "ssl-required" => { + request_size_init(&mut request); + request.ssl_required = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-required", "boolean")); + }, + "audience-segment-id" => { + request_size_init(&mut request); + request.audience_segment_id = Some(value.unwrap_or("").to_string()); + }, + "key-value-targeting-expression.expression" => { + request_key_value_targeting_expression_init(&mut request); + request.key_value_targeting_expression.as_mut().unwrap().expression = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.value" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.dimension-name" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.etag" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.match-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.id" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "default-click-through-event-tag-properties.override-inherited-event-tag" => { + request_default_click_through_event_tag_properties_init(&mut request); + request.default_click_through_event_tag_properties.as_mut().unwrap().override_inherited_event_tag = Some(arg_from_str(value.unwrap_or("false"), err, "default-click-through-event-tag-properties.override-inherited-event-tag", "boolean")); + }, + "default-click-through-event-tag-properties.default-click-through-event-tag-id" => { + request_default_click_through_event_tag_properties_init(&mut request); + request.default_click_through_event_tag_properties.as_mut().unwrap().default_click_through_event_tag_id = Some(value.unwrap_or("").to_string()); + }, + "create-info.time" => { + request_create_info_init(&mut request); + request.create_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "start-time" => { + request_create_info_init(&mut request); + request.start_time = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_create_info_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "compatibility" => { + request_create_info_init(&mut request); + request.compatibility = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_create_info_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_create_info_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_create_info_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "day-part-targeting.user-local-time" => { + request_day_part_targeting_init(&mut request); + request.day_part_targeting.as_mut().unwrap().user_local_time = Some(arg_from_str(value.unwrap_or("false"), err, "day-part-targeting.user-local-time", "boolean")); + }, + "day-part-targeting.hours-of-day" => { + request_day_part_targeting_init(&mut request); + if request.day_part_targeting.as_mut().unwrap().hours_of_day.is_none() { + request.day_part_targeting.as_mut().unwrap().hours_of_day = Some(Default::default()); + } + request.day_part_targeting.as_mut().unwrap().hours_of_day.as_mut().unwrap().push(arg_from_str(value.unwrap_or("-0"), err, "day-part-targeting.hours-of-day", "integer")); + }, + "day-part-targeting.days-of-week" => { + request_day_part_targeting_init(&mut request); + if request.day_part_targeting.as_mut().unwrap().days_of_week.is_none() { + request.day_part_targeting.as_mut().unwrap().days_of_week = Some(Default::default()); + } + request.day_part_targeting.as_mut().unwrap().days_of_week.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "ssl-compliant" => { + request_last_modified_info_init(&mut request); + request.ssl_compliant = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-compliant", "boolean")); + }, + "end-time" => { + request_last_modified_info_init(&mut request); + request.end_time = Some(value.unwrap_or("").to_string()); + }, + "dynamic-click-tracker" => { + request_last_modified_info_init(&mut request); + request.dynamic_click_tracker = Some(arg_from_str(value.unwrap_or("false"), err, "dynamic-click-tracker", "boolean")); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "advertiser-id", "advertiser-id-dimension-value", "archived", "audience-segment-id", "campaign-id", "campaign-id-dimension-value", "click-through-url", "click-through-url-suffix", "click-through-url-suffix-properties", "comments", "compatibility", "create-info", "creative-optimization-configuration-id", "creative-rotation", "custom-click-through-url", "day-part-targeting", "days-of-week", "default-click-through-event-tag-id", "default-click-through-event-tag-properties", "default-landing-page", "delivery-schedule", "dimension-name", "duration", "dynamic-click-tracker", "end-time", "etag", "exclude-countries", "expression", "frequency-cap", "geo-targeting", "hard-cutoff", "height", "hours-of-day", "iab", "id", "id-dimension-value", "impression-ratio", "impressions", "key-value-targeting-expression", "kind", "landing-page-id", "last-modified-info", "match-type", "name", "override-inherited-event-tag", "override-inherited-suffix", "priority", "remarketing-list-expression", "size", "ssl-compliant", "ssl-required", "start-time", "subaccount-id", "time", "type", "user-local-time", "value", "weight-calculation-strategy", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.ads().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _advertiser_groups_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.advertiser_groups().delete(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _advertiser_groups_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.advertiser_groups().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _advertiser_groups_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::AdvertiserGroup::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.advertiser_groups().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _advertiser_groups_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.advertiser_groups().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "sort-field", "ids", "max-results", "page-token", "sort-order"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _advertiser_groups_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::AdvertiserGroup::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.advertiser_groups().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _advertiser_groups_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::AdvertiserGroup::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.advertiser_groups().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _advertisers_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.advertisers().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _advertisers_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Advertiser::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_floodlight_configuration_id_dimension_value_init(request: &mut api::Advertiser) { + if request.floodlight_configuration_id_dimension_value.is_none() { + request.floodlight_configuration_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Advertiser) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "status" => { + request.status = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "default-click-through-event-tag-id" => { + request.default_click_through_event_tag_id = Some(value.unwrap_or("").to_string()); + }, + "original-floodlight-configuration-id" => { + request.original_floodlight_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "click-through-url-suffix" => { + request.click_through_url_suffix = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id" => { + request.floodlight_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.kind" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.value" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.dimension-name" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.etag" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.match-type" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-group-id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.advertiser_group_id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "default-email" => { + request_id_dimension_value_init(&mut request); + request.default_email = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-group-id", "click-through-url-suffix", "default-click-through-event-tag-id", "default-email", "dimension-name", "etag", "floodlight-configuration-id", "floodlight-configuration-id-dimension-value", "id", "id-dimension-value", "kind", "match-type", "name", "original-floodlight-configuration-id", "status", "subaccount-id", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.advertisers().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _advertisers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.advertisers().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "subaccount-id" => { + call = call.subaccount_id(value.unwrap_or("")); + }, + "status" => { + call = call.status(value.unwrap_or("")); + }, + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "only-parent" => { + call = call.only_parent(arg_from_str(value.unwrap_or("false"), err, "only-parent", "boolean")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "include-advertisers-without-groups-only" => { + call = call.include_advertisers_without_groups_only(arg_from_str(value.unwrap_or("false"), err, "include-advertisers-without-groups-only", "boolean")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "floodlight-configuration-ids" => { + call = call.add_floodlight_configuration_ids(value.unwrap_or("")); + }, + "advertiser-group-ids" => { + call = call.add_advertiser_group_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["status", "search-string", "subaccount-id", "include-advertisers-without-groups-only", "sort-field", "ids", "max-results", "page-token", "only-parent", "sort-order", "floodlight-configuration-ids", "advertiser-group-ids"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _advertisers_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Advertiser::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_floodlight_configuration_id_dimension_value_init(request: &mut api::Advertiser) { + if request.floodlight_configuration_id_dimension_value.is_none() { + request.floodlight_configuration_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Advertiser) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "status" => { + request.status = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "default-click-through-event-tag-id" => { + request.default_click_through_event_tag_id = Some(value.unwrap_or("").to_string()); + }, + "original-floodlight-configuration-id" => { + request.original_floodlight_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "click-through-url-suffix" => { + request.click_through_url_suffix = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id" => { + request.floodlight_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.kind" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.value" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.dimension-name" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.etag" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.match-type" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-group-id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.advertiser_group_id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "default-email" => { + request_id_dimension_value_init(&mut request); + request.default_email = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-group-id", "click-through-url-suffix", "default-click-through-event-tag-id", "default-email", "dimension-name", "etag", "floodlight-configuration-id", "floodlight-configuration-id-dimension-value", "id", "id-dimension-value", "kind", "match-type", "name", "original-floodlight-configuration-id", "status", "subaccount-id", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.advertisers().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _advertisers_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Advertiser::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_floodlight_configuration_id_dimension_value_init(request: &mut api::Advertiser) { + if request.floodlight_configuration_id_dimension_value.is_none() { + request.floodlight_configuration_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Advertiser) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "status" => { + request.status = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "default-click-through-event-tag-id" => { + request.default_click_through_event_tag_id = Some(value.unwrap_or("").to_string()); + }, + "original-floodlight-configuration-id" => { + request.original_floodlight_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "click-through-url-suffix" => { + request.click_through_url_suffix = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id" => { + request.floodlight_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.kind" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.value" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.dimension-name" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.etag" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.match-type" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-group-id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.advertiser_group_id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "default-email" => { + request_id_dimension_value_init(&mut request); + request.default_email = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-group-id", "click-through-url-suffix", "default-click-through-event-tag-id", "default-email", "dimension-name", "etag", "floodlight-configuration-id", "floodlight-configuration-id-dimension-value", "id", "id-dimension-value", "kind", "match-type", "name", "original-floodlight-configuration-id", "status", "subaccount-id", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.advertisers().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _browsers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.browsers().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _campaign_creative_associations_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::CampaignCreativeAssociation::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "creative-id" => { + request.creative_id = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["creative-id", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.campaign_creative_associations().insert(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("campaign-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _campaign_creative_associations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.campaign_creative_associations().list(opt.value_of("profile-id").unwrap_or(""), opt.value_of("campaign-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "sort-order", "max-results"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _campaigns_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.campaigns().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _campaigns_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Campaign::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::Campaign) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_click_through_url_suffix_properties_init(request: &mut api::Campaign) { + if request.click_through_url_suffix_properties.is_none() { + request.click_through_url_suffix_properties = Some(Default::default()); + } + } + + fn request_create_info_init(request: &mut api::Campaign) { + if request.create_info.is_none() { + request.create_info = Some(Default::default()); + } + } + + fn request_creative_optimization_configuration_init(request: &mut api::Campaign) { + if request.creative_optimization_configuration.is_none() { + request.creative_optimization_configuration = Some(Default::default()); + } + } + + fn request_default_click_through_event_tag_properties_init(request: &mut api::Campaign) { + if request.default_click_through_event_tag_properties.is_none() { + request.default_click_through_event_tag_properties = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Campaign) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::Campaign) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_lookback_configuration_init(request: &mut api::Campaign) { + if request.lookback_configuration.is_none() { + request.lookback_configuration = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "comment" => { + request.comment = Some(value.unwrap_or("").to_string()); + }, + "start-date" => { + request.start_date = Some(value.unwrap_or("").to_string()); + }, + "end-date" => { + request.end_date = Some(value.unwrap_or("").to_string()); + }, + "click-through-url-suffix-properties.click-through-url-suffix" => { + request_click_through_url_suffix_properties_init(&mut request); + request.click_through_url_suffix_properties.as_mut().unwrap().click_through_url_suffix = Some(value.unwrap_or("").to_string()); + }, + "click-through-url-suffix-properties.override-inherited-suffix" => { + request_click_through_url_suffix_properties_init(&mut request); + request.click_through_url_suffix_properties.as_mut().unwrap().override_inherited_suffix = Some(arg_from_str(value.unwrap_or("false"), err, "click-through-url-suffix-properties.override-inherited-suffix", "boolean")); + }, + "advertiser-id" => { + request_click_through_url_suffix_properties_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "creative-optimization-configuration.optimization-model" => { + request_creative_optimization_configuration_init(&mut request); + request.creative_optimization_configuration.as_mut().unwrap().optimization_model = Some(value.unwrap_or("").to_string()); + }, + "creative-optimization-configuration.id" => { + request_creative_optimization_configuration_init(&mut request); + request.creative_optimization_configuration.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "creative-optimization-configuration.name" => { + request_creative_optimization_configuration_init(&mut request); + request.creative_optimization_configuration.as_mut().unwrap().name = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_creative_optimization_configuration_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_creative_optimization_configuration_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "trafficker-emails" => { + request_creative_optimization_configuration_init(&mut request); + if request.trafficker_emails.is_none() { + request.trafficker_emails = Some(Default::default()); + } + request.trafficker_emails.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "archived" => { + request_creative_optimization_configuration_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "external-id" => { + request_creative_optimization_configuration_init(&mut request); + request.external_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-group-id" => { + request_creative_optimization_configuration_init(&mut request); + request.advertiser_group_id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "billing-invoice-code" => { + request_id_dimension_value_init(&mut request); + request.billing_invoice_code = Some(value.unwrap_or("").to_string()); + }, + "comscore-vce-enabled" => { + request_id_dimension_value_init(&mut request); + request.comscore_vce_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "comscore-vce-enabled", "boolean")); + }, + "creative-group-ids" => { + request_id_dimension_value_init(&mut request); + if request.creative_group_ids.is_none() { + request.creative_group_ids = Some(Default::default()); + } + request.creative_group_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "default-click-through-event-tag-properties.override-inherited-event-tag" => { + request_default_click_through_event_tag_properties_init(&mut request); + request.default_click_through_event_tag_properties.as_mut().unwrap().override_inherited_event_tag = Some(arg_from_str(value.unwrap_or("false"), err, "default-click-through-event-tag-properties.override-inherited-event-tag", "boolean")); + }, + "default-click-through-event-tag-properties.default-click-through-event-tag-id" => { + request_default_click_through_event_tag_properties_init(&mut request); + request.default_click_through_event_tag_properties.as_mut().unwrap().default_click_through_event_tag_id = Some(value.unwrap_or("").to_string()); + }, + "create-info.time" => { + request_create_info_init(&mut request); + request.create_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_create_info_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_create_info_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_create_info_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "lookback-configuration.click-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().click_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.click-duration", "integer")); + }, + "lookback-configuration.post-impression-activities-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().post_impression_activities_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.post-impression-activities-duration", "integer")); + }, + "nielsen-ocr-enabled" => { + request_lookback_configuration_init(&mut request); + request.nielsen_ocr_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "nielsen-ocr-enabled", "boolean")); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-group-id", "advertiser-id", "advertiser-id-dimension-value", "archived", "billing-invoice-code", "click-duration", "click-through-url-suffix", "click-through-url-suffix-properties", "comment", "comscore-vce-enabled", "create-info", "creative-group-ids", "creative-optimization-configuration", "default-click-through-event-tag-id", "default-click-through-event-tag-properties", "dimension-name", "end-date", "etag", "external-id", "id", "id-dimension-value", "kind", "last-modified-info", "lookback-configuration", "match-type", "name", "nielsen-ocr-enabled", "optimization-model", "override-inherited-event-tag", "override-inherited-suffix", "post-impression-activities-duration", "start-date", "subaccount-id", "time", "trafficker-emails", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.campaigns().insert(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("default-landing-page-name").unwrap_or(""), opt.value_of("default-landing-page-url").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _campaigns_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.campaigns().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "subaccount-id" => { + call = call.subaccount_id(value.unwrap_or("")); + }, + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "overridden-event-tag-id" => { + call = call.overridden_event_tag_id(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "excluded-ids" => { + call = call.add_excluded_ids(value.unwrap_or("")); + }, + "at-least-one-optimization-activity" => { + call = call.at_least_one_optimization_activity(arg_from_str(value.unwrap_or("false"), err, "at-least-one-optimization-activity", "boolean")); + }, + "archived" => { + call = call.archived(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "advertiser-ids" => { + call = call.add_advertiser_ids(value.unwrap_or("")); + }, + "advertiser-group-ids" => { + call = call.add_advertiser_group_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["archived", "search-string", "subaccount-id", "sort-field", "advertiser-ids", "ids", "max-results", "excluded-ids", "page-token", "advertiser-group-ids", "sort-order", "overridden-event-tag-id", "at-least-one-optimization-activity"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _campaigns_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Campaign::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::Campaign) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_click_through_url_suffix_properties_init(request: &mut api::Campaign) { + if request.click_through_url_suffix_properties.is_none() { + request.click_through_url_suffix_properties = Some(Default::default()); + } + } + + fn request_create_info_init(request: &mut api::Campaign) { + if request.create_info.is_none() { + request.create_info = Some(Default::default()); + } + } + + fn request_creative_optimization_configuration_init(request: &mut api::Campaign) { + if request.creative_optimization_configuration.is_none() { + request.creative_optimization_configuration = Some(Default::default()); + } + } + + fn request_default_click_through_event_tag_properties_init(request: &mut api::Campaign) { + if request.default_click_through_event_tag_properties.is_none() { + request.default_click_through_event_tag_properties = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Campaign) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::Campaign) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_lookback_configuration_init(request: &mut api::Campaign) { + if request.lookback_configuration.is_none() { + request.lookback_configuration = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "comment" => { + request.comment = Some(value.unwrap_or("").to_string()); + }, + "start-date" => { + request.start_date = Some(value.unwrap_or("").to_string()); + }, + "end-date" => { + request.end_date = Some(value.unwrap_or("").to_string()); + }, + "click-through-url-suffix-properties.click-through-url-suffix" => { + request_click_through_url_suffix_properties_init(&mut request); + request.click_through_url_suffix_properties.as_mut().unwrap().click_through_url_suffix = Some(value.unwrap_or("").to_string()); + }, + "click-through-url-suffix-properties.override-inherited-suffix" => { + request_click_through_url_suffix_properties_init(&mut request); + request.click_through_url_suffix_properties.as_mut().unwrap().override_inherited_suffix = Some(arg_from_str(value.unwrap_or("false"), err, "click-through-url-suffix-properties.override-inherited-suffix", "boolean")); + }, + "advertiser-id" => { + request_click_through_url_suffix_properties_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "creative-optimization-configuration.optimization-model" => { + request_creative_optimization_configuration_init(&mut request); + request.creative_optimization_configuration.as_mut().unwrap().optimization_model = Some(value.unwrap_or("").to_string()); + }, + "creative-optimization-configuration.id" => { + request_creative_optimization_configuration_init(&mut request); + request.creative_optimization_configuration.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "creative-optimization-configuration.name" => { + request_creative_optimization_configuration_init(&mut request); + request.creative_optimization_configuration.as_mut().unwrap().name = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_creative_optimization_configuration_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_creative_optimization_configuration_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "trafficker-emails" => { + request_creative_optimization_configuration_init(&mut request); + if request.trafficker_emails.is_none() { + request.trafficker_emails = Some(Default::default()); + } + request.trafficker_emails.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "archived" => { + request_creative_optimization_configuration_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "external-id" => { + request_creative_optimization_configuration_init(&mut request); + request.external_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-group-id" => { + request_creative_optimization_configuration_init(&mut request); + request.advertiser_group_id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "billing-invoice-code" => { + request_id_dimension_value_init(&mut request); + request.billing_invoice_code = Some(value.unwrap_or("").to_string()); + }, + "comscore-vce-enabled" => { + request_id_dimension_value_init(&mut request); + request.comscore_vce_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "comscore-vce-enabled", "boolean")); + }, + "creative-group-ids" => { + request_id_dimension_value_init(&mut request); + if request.creative_group_ids.is_none() { + request.creative_group_ids = Some(Default::default()); + } + request.creative_group_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "default-click-through-event-tag-properties.override-inherited-event-tag" => { + request_default_click_through_event_tag_properties_init(&mut request); + request.default_click_through_event_tag_properties.as_mut().unwrap().override_inherited_event_tag = Some(arg_from_str(value.unwrap_or("false"), err, "default-click-through-event-tag-properties.override-inherited-event-tag", "boolean")); + }, + "default-click-through-event-tag-properties.default-click-through-event-tag-id" => { + request_default_click_through_event_tag_properties_init(&mut request); + request.default_click_through_event_tag_properties.as_mut().unwrap().default_click_through_event_tag_id = Some(value.unwrap_or("").to_string()); + }, + "create-info.time" => { + request_create_info_init(&mut request); + request.create_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_create_info_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_create_info_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_create_info_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "lookback-configuration.click-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().click_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.click-duration", "integer")); + }, + "lookback-configuration.post-impression-activities-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().post_impression_activities_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.post-impression-activities-duration", "integer")); + }, + "nielsen-ocr-enabled" => { + request_lookback_configuration_init(&mut request); + request.nielsen_ocr_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "nielsen-ocr-enabled", "boolean")); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-group-id", "advertiser-id", "advertiser-id-dimension-value", "archived", "billing-invoice-code", "click-duration", "click-through-url-suffix", "click-through-url-suffix-properties", "comment", "comscore-vce-enabled", "create-info", "creative-group-ids", "creative-optimization-configuration", "default-click-through-event-tag-id", "default-click-through-event-tag-properties", "dimension-name", "end-date", "etag", "external-id", "id", "id-dimension-value", "kind", "last-modified-info", "lookback-configuration", "match-type", "name", "nielsen-ocr-enabled", "optimization-model", "override-inherited-event-tag", "override-inherited-suffix", "post-impression-activities-duration", "start-date", "subaccount-id", "time", "trafficker-emails", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.campaigns().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _campaigns_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Campaign::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::Campaign) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_click_through_url_suffix_properties_init(request: &mut api::Campaign) { + if request.click_through_url_suffix_properties.is_none() { + request.click_through_url_suffix_properties = Some(Default::default()); + } + } + + fn request_create_info_init(request: &mut api::Campaign) { + if request.create_info.is_none() { + request.create_info = Some(Default::default()); + } + } + + fn request_creative_optimization_configuration_init(request: &mut api::Campaign) { + if request.creative_optimization_configuration.is_none() { + request.creative_optimization_configuration = Some(Default::default()); + } + } + + fn request_default_click_through_event_tag_properties_init(request: &mut api::Campaign) { + if request.default_click_through_event_tag_properties.is_none() { + request.default_click_through_event_tag_properties = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Campaign) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::Campaign) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_lookback_configuration_init(request: &mut api::Campaign) { + if request.lookback_configuration.is_none() { + request.lookback_configuration = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "comment" => { + request.comment = Some(value.unwrap_or("").to_string()); + }, + "start-date" => { + request.start_date = Some(value.unwrap_or("").to_string()); + }, + "end-date" => { + request.end_date = Some(value.unwrap_or("").to_string()); + }, + "click-through-url-suffix-properties.click-through-url-suffix" => { + request_click_through_url_suffix_properties_init(&mut request); + request.click_through_url_suffix_properties.as_mut().unwrap().click_through_url_suffix = Some(value.unwrap_or("").to_string()); + }, + "click-through-url-suffix-properties.override-inherited-suffix" => { + request_click_through_url_suffix_properties_init(&mut request); + request.click_through_url_suffix_properties.as_mut().unwrap().override_inherited_suffix = Some(arg_from_str(value.unwrap_or("false"), err, "click-through-url-suffix-properties.override-inherited-suffix", "boolean")); + }, + "advertiser-id" => { + request_click_through_url_suffix_properties_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "creative-optimization-configuration.optimization-model" => { + request_creative_optimization_configuration_init(&mut request); + request.creative_optimization_configuration.as_mut().unwrap().optimization_model = Some(value.unwrap_or("").to_string()); + }, + "creative-optimization-configuration.id" => { + request_creative_optimization_configuration_init(&mut request); + request.creative_optimization_configuration.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "creative-optimization-configuration.name" => { + request_creative_optimization_configuration_init(&mut request); + request.creative_optimization_configuration.as_mut().unwrap().name = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_creative_optimization_configuration_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_creative_optimization_configuration_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "trafficker-emails" => { + request_creative_optimization_configuration_init(&mut request); + if request.trafficker_emails.is_none() { + request.trafficker_emails = Some(Default::default()); + } + request.trafficker_emails.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "archived" => { + request_creative_optimization_configuration_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "external-id" => { + request_creative_optimization_configuration_init(&mut request); + request.external_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-group-id" => { + request_creative_optimization_configuration_init(&mut request); + request.advertiser_group_id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "billing-invoice-code" => { + request_id_dimension_value_init(&mut request); + request.billing_invoice_code = Some(value.unwrap_or("").to_string()); + }, + "comscore-vce-enabled" => { + request_id_dimension_value_init(&mut request); + request.comscore_vce_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "comscore-vce-enabled", "boolean")); + }, + "creative-group-ids" => { + request_id_dimension_value_init(&mut request); + if request.creative_group_ids.is_none() { + request.creative_group_ids = Some(Default::default()); + } + request.creative_group_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "default-click-through-event-tag-properties.override-inherited-event-tag" => { + request_default_click_through_event_tag_properties_init(&mut request); + request.default_click_through_event_tag_properties.as_mut().unwrap().override_inherited_event_tag = Some(arg_from_str(value.unwrap_or("false"), err, "default-click-through-event-tag-properties.override-inherited-event-tag", "boolean")); + }, + "default-click-through-event-tag-properties.default-click-through-event-tag-id" => { + request_default_click_through_event_tag_properties_init(&mut request); + request.default_click_through_event_tag_properties.as_mut().unwrap().default_click_through_event_tag_id = Some(value.unwrap_or("").to_string()); + }, + "create-info.time" => { + request_create_info_init(&mut request); + request.create_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_create_info_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_create_info_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_create_info_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "lookback-configuration.click-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().click_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.click-duration", "integer")); + }, + "lookback-configuration.post-impression-activities-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().post_impression_activities_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.post-impression-activities-duration", "integer")); + }, + "nielsen-ocr-enabled" => { + request_lookback_configuration_init(&mut request); + request.nielsen_ocr_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "nielsen-ocr-enabled", "boolean")); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-group-id", "advertiser-id", "advertiser-id-dimension-value", "archived", "billing-invoice-code", "click-duration", "click-through-url-suffix", "click-through-url-suffix-properties", "comment", "comscore-vce-enabled", "create-info", "creative-group-ids", "creative-optimization-configuration", "default-click-through-event-tag-id", "default-click-through-event-tag-properties", "dimension-name", "end-date", "etag", "external-id", "id", "id-dimension-value", "kind", "last-modified-info", "lookback-configuration", "match-type", "name", "nielsen-ocr-enabled", "optimization-model", "override-inherited-event-tag", "override-inherited-suffix", "post-impression-activities-duration", "start-date", "subaccount-id", "time", "trafficker-emails", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.campaigns().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _change_logs_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.change_logs().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _change_logs_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.change_logs().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "user-profile-ids" => { + call = call.add_user_profile_ids(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "object-type" => { + call = call.object_type(value.unwrap_or("")); + }, + "object-ids" => { + call = call.add_object_ids(value.unwrap_or("")); + }, + "min-change-time" => { + call = call.min_change_time(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "max-change-time" => { + call = call.max_change_time(value.unwrap_or("")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "action" => { + call = call.action(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["min-change-time", "search-string", "max-change-time", "user-profile-ids", "ids", "max-results", "object-ids", "page-token", "action", "object-type"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _cities_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.cities().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "region-dart-ids" => { + call = call.add_region_dart_ids(value.unwrap_or("")); + }, + "name-prefix" => { + call = call.name_prefix(value.unwrap_or("")); + }, + "dart-ids" => { + call = call.add_dart_ids(value.unwrap_or("")); + }, + "country-dart-ids" => { + call = call.add_country_dart_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["dart-ids", "country-dart-ids", "region-dart-ids", "name-prefix"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _connection_types_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.connection_types().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _connection_types_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.connection_types().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _content_categories_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.content_categories().delete(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _content_categories_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.content_categories().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _content_categories_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::ContentCategory::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.content_categories().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _content_categories_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.content_categories().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "sort-field", "ids", "max-results", "page-token", "sort-order"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _content_categories_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::ContentCategory::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.content_categories().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _content_categories_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::ContentCategory::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.content_categories().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _countries_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.countries().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("dart-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _countries_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.countries().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_assets_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::CreativeAssetMetadata::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_asset_identifier_init(request: &mut api::CreativeAssetMetadata) { + if request.asset_identifier.is_none() { + request.asset_identifier = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "warned-validation-rules" => { + if request.warned_validation_rules.is_none() { + request.warned_validation_rules = Some(Default::default()); + } + request.warned_validation_rules.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "detected-features" => { + if request.detected_features.is_none() { + request.detected_features = Some(Default::default()); + } + request.detected_features.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "asset-identifier.type" => { + request_asset_identifier_init(&mut request); + request.asset_identifier.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); + }, + "asset-identifier.name" => { + request_asset_identifier_init(&mut request); + request.asset_identifier.as_mut().unwrap().name = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["asset-identifier", "detected-features", "kind", "name", "type", "warned-validation-rules"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.creative_assets().insert(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("advertiser-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_field_values_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.creative_field_values().delete(opt.value_of("profile-id").unwrap_or(""), opt.value_of("creative-field-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _creative_field_values_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.creative_field_values().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("creative-field-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_field_values_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::CreativeFieldValue::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "value" => { + request.value = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "kind", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.creative_field_values().insert(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("creative-field-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_field_values_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.creative_field_values().list(opt.value_of("profile-id").unwrap_or(""), opt.value_of("creative-field-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "sort-field", "ids", "max-results", "page-token", "sort-order"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_field_values_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::CreativeFieldValue::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "value" => { + request.value = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "kind", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.creative_field_values().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("creative-field-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_field_values_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::CreativeFieldValue::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "value" => { + request.value = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "kind", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.creative_field_values().update(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("creative-field-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_fields_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.creative_fields().delete(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _creative_fields_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.creative_fields().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_fields_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::CreativeField::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::CreativeField) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "dimension-name", "etag", "id", "kind", "match-type", "name", "subaccount-id", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.creative_fields().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_fields_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.creative_fields().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "advertiser-ids" => { + call = call.add_advertiser_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "sort-field", "advertiser-ids", "ids", "max-results", "page-token", "sort-order"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_fields_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::CreativeField::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::CreativeField) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "dimension-name", "etag", "id", "kind", "match-type", "name", "subaccount-id", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.creative_fields().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_fields_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::CreativeField::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::CreativeField) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "dimension-name", "etag", "id", "kind", "match-type", "name", "subaccount-id", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.creative_fields().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_groups_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.creative_groups().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_groups_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::CreativeGroup::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::CreativeGroup) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "group-number" => { + request.group_number = Some(arg_from_str(value.unwrap_or("-0"), err, "group-number", "integer")); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "dimension-name", "etag", "group-number", "id", "kind", "match-type", "name", "subaccount-id", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.creative_groups().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_groups_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.creative_groups().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "group-number" => { + call = call.group_number(arg_from_str(value.unwrap_or("-0"), err, "group-number", "integer")); + }, + "advertiser-ids" => { + call = call.add_advertiser_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "sort-field", "advertiser-ids", "ids", "max-results", "group-number", "page-token", "sort-order"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_groups_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::CreativeGroup::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::CreativeGroup) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "group-number" => { + request.group_number = Some(arg_from_str(value.unwrap_or("-0"), err, "group-number", "integer")); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "dimension-name", "etag", "group-number", "id", "kind", "match-type", "name", "subaccount-id", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.creative_groups().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creative_groups_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::CreativeGroup::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::CreativeGroup) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "group-number" => { + request.group_number = Some(arg_from_str(value.unwrap_or("-0"), err, "group-number", "integer")); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "dimension-name", "etag", "group-number", "id", "kind", "match-type", "name", "subaccount-id", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.creative_groups().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creatives_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.creatives().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creatives_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Creative::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_backup_image_target_window_init(request: &mut api::Creative) { + if request.backup_image_target_window.is_none() { + request.backup_image_target_window = Some(Default::default()); + } + } + + fn request_fs_command_init(request: &mut api::Creative) { + if request.fs_command.is_none() { + request.fs_command = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Creative) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::Creative) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_rendering_id_dimension_value_init(request: &mut api::Creative) { + if request.rendering_id_dimension_value.is_none() { + request.rendering_id_dimension_value = Some(Default::default()); + } + } + + fn request_size_init(request: &mut api::Creative) { + if request.size.is_none() { + request.size = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "artwork-type" => { + request.artwork_type = Some(value.unwrap_or("").to_string()); + }, + "latest-trafficked-creative-id" => { + request.latest_trafficked_creative_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "required-flash-plugin-version" => { + request.required_flash_plugin_version = Some(value.unwrap_or("").to_string()); + }, + "fs-command.window-height" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().window_height = Some(arg_from_str(value.unwrap_or("-0"), err, "fs-command.window-height", "integer")); + }, + "fs-command.top" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().top = Some(arg_from_str(value.unwrap_or("-0"), err, "fs-command.top", "integer")); + }, + "fs-command.window-width" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().window_width = Some(arg_from_str(value.unwrap_or("-0"), err, "fs-command.window-width", "integer")); + }, + "fs-command.position-option" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().position_option = Some(value.unwrap_or("").to_string()); + }, + "fs-command.left" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().left = Some(arg_from_str(value.unwrap_or("-0"), err, "fs-command.left", "integer")); + }, + "rendering-id-dimension-value.kind" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.value" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.dimension-name" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.etag" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.match-type" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.id" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_rendering_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "size.width" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().width = Some(arg_from_str(value.unwrap_or("-0"), err, "size.width", "integer")); + }, + "size.kind" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "size.iab" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().iab = Some(arg_from_str(value.unwrap_or("false"), err, "size.iab", "boolean")); + }, + "size.id" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.height" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().height = Some(arg_from_str(value.unwrap_or("-0"), err, "size.height", "integer")); + }, + "studio-trafficked-creative-id" => { + request_size_init(&mut request); + request.studio_trafficked_creative_id = Some(value.unwrap_or("").to_string()); + }, + "archived" => { + request_size_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "override-css" => { + request_size_init(&mut request); + request.override_css = Some(value.unwrap_or("").to_string()); + }, + "required-flash-version" => { + request_size_init(&mut request); + request.required_flash_version = Some(arg_from_str(value.unwrap_or("-0"), err, "required-flash-version", "integer")); + }, + "rendering-id" => { + request_size_init(&mut request); + request.rendering_id = Some(value.unwrap_or("").to_string()); + }, + "video-description" => { + request_size_init(&mut request); + request.video_description = Some(value.unwrap_or("").to_string()); + }, + "third-party-backup-image-impressions-url" => { + request_size_init(&mut request); + request.third_party_backup_image_impressions_url = Some(value.unwrap_or("").to_string()); + }, + "version" => { + request_size_init(&mut request); + request.version = Some(arg_from_str(value.unwrap_or("-0"), err, "version", "integer")); + }, + "background-color" => { + request_size_init(&mut request); + request.background_color = Some(value.unwrap_or("").to_string()); + }, + "custom-key-values" => { + request_size_init(&mut request); + if request.custom_key_values.is_none() { + request.custom_key_values = Some(Default::default()); + } + request.custom_key_values.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "html-code" => { + request_id_dimension_value_init(&mut request); + request.html_code = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "type" => { + request_id_dimension_value_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "total-file-size" => { + request_id_dimension_value_init(&mut request); + request.total_file_size = Some(value.unwrap_or("").to_string()); + }, + "third-party-rich-media-impressions-url" => { + request_id_dimension_value_init(&mut request); + request.third_party_rich_media_impressions_url = Some(value.unwrap_or("").to_string()); + }, + "studio-advertiser-id" => { + request_id_dimension_value_init(&mut request); + request.studio_advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "html-code-locked" => { + request_id_dimension_value_init(&mut request); + request.html_code_locked = Some(arg_from_str(value.unwrap_or("false"), err, "html-code-locked", "boolean")); + }, + "redirect-url" => { + request_id_dimension_value_init(&mut request); + request.redirect_url = Some(value.unwrap_or("").to_string()); + }, + "commercial-id" => { + request_id_dimension_value_init(&mut request); + request.commercial_id = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_id_dimension_value_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "backup-image-reporting-label" => { + request_id_dimension_value_init(&mut request); + request.backup_image_reporting_label = Some(value.unwrap_or("").to_string()); + }, + "compatibility" => { + request_id_dimension_value_init(&mut request); + if request.compatibility.is_none() { + request.compatibility = Some(Default::default()); + } + request.compatibility.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "ad-parameters" => { + request_id_dimension_value_init(&mut request); + request.ad_parameters = Some(value.unwrap_or("").to_string()); + }, + "ad-tag-keys" => { + request_id_dimension_value_init(&mut request); + if request.ad_tag_keys.is_none() { + request.ad_tag_keys = Some(Default::default()); + } + request.ad_tag_keys.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "kind" => { + request_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_id_dimension_value_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_id_dimension_value_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "convert-flash-to-html5" => { + request_id_dimension_value_init(&mut request); + request.convert_flash_to_html5 = Some(arg_from_str(value.unwrap_or("false"), err, "convert-flash-to-html5", "boolean")); + }, + "video-duration" => { + request_id_dimension_value_init(&mut request); + request.video_duration = Some(arg_from_str(value.unwrap_or("0.0"), err, "video-duration", "number")); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "backup-image-click-through-url" => { + request_last_modified_info_init(&mut request); + request.backup_image_click_through_url = Some(value.unwrap_or("").to_string()); + }, + "ssl-compliant" => { + request_last_modified_info_init(&mut request); + request.ssl_compliant = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-compliant", "boolean")); + }, + "studio-creative-id" => { + request_last_modified_info_init(&mut request); + request.studio_creative_id = Some(value.unwrap_or("").to_string()); + }, + "authoring-tool" => { + request_last_modified_info_init(&mut request); + request.authoring_tool = Some(value.unwrap_or("").to_string()); + }, + "allow-script-access" => { + request_last_modified_info_init(&mut request); + request.allow_script_access = Some(arg_from_str(value.unwrap_or("false"), err, "allow-script-access", "boolean")); + }, + "companion-creatives" => { + request_last_modified_info_init(&mut request); + if request.companion_creatives.is_none() { + request.companion_creatives = Some(Default::default()); + } + request.companion_creatives.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "auto-advance-images" => { + request_last_modified_info_init(&mut request); + request.auto_advance_images = Some(arg_from_str(value.unwrap_or("false"), err, "auto-advance-images", "boolean")); + }, + "backup-image-features" => { + request_last_modified_info_init(&mut request); + if request.backup_image_features.is_none() { + request.backup_image_features = Some(Default::default()); + } + request.backup_image_features.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "backup-image-target-window.custom-html" => { + request_backup_image_target_window_init(&mut request); + request.backup_image_target_window.as_mut().unwrap().custom_html = Some(value.unwrap_or("").to_string()); + }, + "backup-image-target-window.target-window-option" => { + request_backup_image_target_window_init(&mut request); + request.backup_image_target_window.as_mut().unwrap().target_window_option = Some(value.unwrap_or("").to_string()); + }, + "skippable" => { + request_backup_image_target_window_init(&mut request); + request.skippable = Some(arg_from_str(value.unwrap_or("false"), err, "skippable", "boolean")); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "ad-parameters", "ad-tag-keys", "advertiser-id", "allow-script-access", "archived", "artwork-type", "authoring-tool", "auto-advance-images", "background-color", "backup-image-click-through-url", "backup-image-features", "backup-image-reporting-label", "backup-image-target-window", "commercial-id", "companion-creatives", "compatibility", "convert-flash-to-html5", "custom-html", "custom-key-values", "dimension-name", "etag", "fs-command", "height", "html-code", "html-code-locked", "iab", "id", "id-dimension-value", "kind", "last-modified-info", "latest-trafficked-creative-id", "left", "match-type", "name", "override-css", "position-option", "redirect-url", "rendering-id", "rendering-id-dimension-value", "required-flash-plugin-version", "required-flash-version", "size", "skippable", "ssl-compliant", "studio-advertiser-id", "studio-creative-id", "studio-trafficked-creative-id", "subaccount-id", "target-window-option", "third-party-backup-image-impressions-url", "third-party-rich-media-impressions-url", "time", "top", "total-file-size", "type", "value", "version", "video-description", "video-duration", "width", "window-height", "window-width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.creatives().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creatives_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.creatives().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "types" => { + call = call.add_types(value.unwrap_or("")); + }, + "studio-creative-id" => { + call = call.studio_creative_id(value.unwrap_or("")); + }, + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "size-ids" => { + call = call.add_size_ids(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "rendering-ids" => { + call = call.add_rendering_ids(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "creative-field-ids" => { + call = call.add_creative_field_ids(value.unwrap_or("")); + }, + "companion-creative-ids" => { + call = call.add_companion_creative_ids(value.unwrap_or("")); + }, + "campaign-id" => { + call = call.campaign_id(value.unwrap_or("")); + }, + "archived" => { + call = call.archived(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "advertiser-id" => { + call = call.advertiser_id(value.unwrap_or("")); + }, + "active" => { + call = call.active(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["advertiser-id", "archived", "search-string", "max-results", "campaign-id", "sort-field", "rendering-ids", "ids", "studio-creative-id", "size-ids", "page-token", "sort-order", "companion-creative-ids", "active", "creative-field-ids", "types"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creatives_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Creative::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_backup_image_target_window_init(request: &mut api::Creative) { + if request.backup_image_target_window.is_none() { + request.backup_image_target_window = Some(Default::default()); + } + } + + fn request_fs_command_init(request: &mut api::Creative) { + if request.fs_command.is_none() { + request.fs_command = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Creative) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::Creative) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_rendering_id_dimension_value_init(request: &mut api::Creative) { + if request.rendering_id_dimension_value.is_none() { + request.rendering_id_dimension_value = Some(Default::default()); + } + } + + fn request_size_init(request: &mut api::Creative) { + if request.size.is_none() { + request.size = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "artwork-type" => { + request.artwork_type = Some(value.unwrap_or("").to_string()); + }, + "latest-trafficked-creative-id" => { + request.latest_trafficked_creative_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "required-flash-plugin-version" => { + request.required_flash_plugin_version = Some(value.unwrap_or("").to_string()); + }, + "fs-command.window-height" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().window_height = Some(arg_from_str(value.unwrap_or("-0"), err, "fs-command.window-height", "integer")); + }, + "fs-command.top" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().top = Some(arg_from_str(value.unwrap_or("-0"), err, "fs-command.top", "integer")); + }, + "fs-command.window-width" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().window_width = Some(arg_from_str(value.unwrap_or("-0"), err, "fs-command.window-width", "integer")); + }, + "fs-command.position-option" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().position_option = Some(value.unwrap_or("").to_string()); + }, + "fs-command.left" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().left = Some(arg_from_str(value.unwrap_or("-0"), err, "fs-command.left", "integer")); + }, + "rendering-id-dimension-value.kind" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.value" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.dimension-name" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.etag" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.match-type" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.id" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_rendering_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "size.width" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().width = Some(arg_from_str(value.unwrap_or("-0"), err, "size.width", "integer")); + }, + "size.kind" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "size.iab" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().iab = Some(arg_from_str(value.unwrap_or("false"), err, "size.iab", "boolean")); + }, + "size.id" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.height" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().height = Some(arg_from_str(value.unwrap_or("-0"), err, "size.height", "integer")); + }, + "studio-trafficked-creative-id" => { + request_size_init(&mut request); + request.studio_trafficked_creative_id = Some(value.unwrap_or("").to_string()); + }, + "archived" => { + request_size_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "override-css" => { + request_size_init(&mut request); + request.override_css = Some(value.unwrap_or("").to_string()); + }, + "required-flash-version" => { + request_size_init(&mut request); + request.required_flash_version = Some(arg_from_str(value.unwrap_or("-0"), err, "required-flash-version", "integer")); + }, + "rendering-id" => { + request_size_init(&mut request); + request.rendering_id = Some(value.unwrap_or("").to_string()); + }, + "video-description" => { + request_size_init(&mut request); + request.video_description = Some(value.unwrap_or("").to_string()); + }, + "third-party-backup-image-impressions-url" => { + request_size_init(&mut request); + request.third_party_backup_image_impressions_url = Some(value.unwrap_or("").to_string()); + }, + "version" => { + request_size_init(&mut request); + request.version = Some(arg_from_str(value.unwrap_or("-0"), err, "version", "integer")); + }, + "background-color" => { + request_size_init(&mut request); + request.background_color = Some(value.unwrap_or("").to_string()); + }, + "custom-key-values" => { + request_size_init(&mut request); + if request.custom_key_values.is_none() { + request.custom_key_values = Some(Default::default()); + } + request.custom_key_values.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "html-code" => { + request_id_dimension_value_init(&mut request); + request.html_code = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "type" => { + request_id_dimension_value_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "total-file-size" => { + request_id_dimension_value_init(&mut request); + request.total_file_size = Some(value.unwrap_or("").to_string()); + }, + "third-party-rich-media-impressions-url" => { + request_id_dimension_value_init(&mut request); + request.third_party_rich_media_impressions_url = Some(value.unwrap_or("").to_string()); + }, + "studio-advertiser-id" => { + request_id_dimension_value_init(&mut request); + request.studio_advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "html-code-locked" => { + request_id_dimension_value_init(&mut request); + request.html_code_locked = Some(arg_from_str(value.unwrap_or("false"), err, "html-code-locked", "boolean")); + }, + "redirect-url" => { + request_id_dimension_value_init(&mut request); + request.redirect_url = Some(value.unwrap_or("").to_string()); + }, + "commercial-id" => { + request_id_dimension_value_init(&mut request); + request.commercial_id = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_id_dimension_value_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "backup-image-reporting-label" => { + request_id_dimension_value_init(&mut request); + request.backup_image_reporting_label = Some(value.unwrap_or("").to_string()); + }, + "compatibility" => { + request_id_dimension_value_init(&mut request); + if request.compatibility.is_none() { + request.compatibility = Some(Default::default()); + } + request.compatibility.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "ad-parameters" => { + request_id_dimension_value_init(&mut request); + request.ad_parameters = Some(value.unwrap_or("").to_string()); + }, + "ad-tag-keys" => { + request_id_dimension_value_init(&mut request); + if request.ad_tag_keys.is_none() { + request.ad_tag_keys = Some(Default::default()); + } + request.ad_tag_keys.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "kind" => { + request_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_id_dimension_value_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_id_dimension_value_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "convert-flash-to-html5" => { + request_id_dimension_value_init(&mut request); + request.convert_flash_to_html5 = Some(arg_from_str(value.unwrap_or("false"), err, "convert-flash-to-html5", "boolean")); + }, + "video-duration" => { + request_id_dimension_value_init(&mut request); + request.video_duration = Some(arg_from_str(value.unwrap_or("0.0"), err, "video-duration", "number")); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "backup-image-click-through-url" => { + request_last_modified_info_init(&mut request); + request.backup_image_click_through_url = Some(value.unwrap_or("").to_string()); + }, + "ssl-compliant" => { + request_last_modified_info_init(&mut request); + request.ssl_compliant = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-compliant", "boolean")); + }, + "studio-creative-id" => { + request_last_modified_info_init(&mut request); + request.studio_creative_id = Some(value.unwrap_or("").to_string()); + }, + "authoring-tool" => { + request_last_modified_info_init(&mut request); + request.authoring_tool = Some(value.unwrap_or("").to_string()); + }, + "allow-script-access" => { + request_last_modified_info_init(&mut request); + request.allow_script_access = Some(arg_from_str(value.unwrap_or("false"), err, "allow-script-access", "boolean")); + }, + "companion-creatives" => { + request_last_modified_info_init(&mut request); + if request.companion_creatives.is_none() { + request.companion_creatives = Some(Default::default()); + } + request.companion_creatives.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "auto-advance-images" => { + request_last_modified_info_init(&mut request); + request.auto_advance_images = Some(arg_from_str(value.unwrap_or("false"), err, "auto-advance-images", "boolean")); + }, + "backup-image-features" => { + request_last_modified_info_init(&mut request); + if request.backup_image_features.is_none() { + request.backup_image_features = Some(Default::default()); + } + request.backup_image_features.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "backup-image-target-window.custom-html" => { + request_backup_image_target_window_init(&mut request); + request.backup_image_target_window.as_mut().unwrap().custom_html = Some(value.unwrap_or("").to_string()); + }, + "backup-image-target-window.target-window-option" => { + request_backup_image_target_window_init(&mut request); + request.backup_image_target_window.as_mut().unwrap().target_window_option = Some(value.unwrap_or("").to_string()); + }, + "skippable" => { + request_backup_image_target_window_init(&mut request); + request.skippable = Some(arg_from_str(value.unwrap_or("false"), err, "skippable", "boolean")); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "ad-parameters", "ad-tag-keys", "advertiser-id", "allow-script-access", "archived", "artwork-type", "authoring-tool", "auto-advance-images", "background-color", "backup-image-click-through-url", "backup-image-features", "backup-image-reporting-label", "backup-image-target-window", "commercial-id", "companion-creatives", "compatibility", "convert-flash-to-html5", "custom-html", "custom-key-values", "dimension-name", "etag", "fs-command", "height", "html-code", "html-code-locked", "iab", "id", "id-dimension-value", "kind", "last-modified-info", "latest-trafficked-creative-id", "left", "match-type", "name", "override-css", "position-option", "redirect-url", "rendering-id", "rendering-id-dimension-value", "required-flash-plugin-version", "required-flash-version", "size", "skippable", "ssl-compliant", "studio-advertiser-id", "studio-creative-id", "studio-trafficked-creative-id", "subaccount-id", "target-window-option", "third-party-backup-image-impressions-url", "third-party-rich-media-impressions-url", "time", "top", "total-file-size", "type", "value", "version", "video-description", "video-duration", "width", "window-height", "window-width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.creatives().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _creatives_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Creative::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_backup_image_target_window_init(request: &mut api::Creative) { + if request.backup_image_target_window.is_none() { + request.backup_image_target_window = Some(Default::default()); + } + } + + fn request_fs_command_init(request: &mut api::Creative) { + if request.fs_command.is_none() { + request.fs_command = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Creative) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::Creative) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_rendering_id_dimension_value_init(request: &mut api::Creative) { + if request.rendering_id_dimension_value.is_none() { + request.rendering_id_dimension_value = Some(Default::default()); + } + } + + fn request_size_init(request: &mut api::Creative) { + if request.size.is_none() { + request.size = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "artwork-type" => { + request.artwork_type = Some(value.unwrap_or("").to_string()); + }, + "latest-trafficked-creative-id" => { + request.latest_trafficked_creative_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "required-flash-plugin-version" => { + request.required_flash_plugin_version = Some(value.unwrap_or("").to_string()); + }, + "fs-command.window-height" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().window_height = Some(arg_from_str(value.unwrap_or("-0"), err, "fs-command.window-height", "integer")); + }, + "fs-command.top" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().top = Some(arg_from_str(value.unwrap_or("-0"), err, "fs-command.top", "integer")); + }, + "fs-command.window-width" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().window_width = Some(arg_from_str(value.unwrap_or("-0"), err, "fs-command.window-width", "integer")); + }, + "fs-command.position-option" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().position_option = Some(value.unwrap_or("").to_string()); + }, + "fs-command.left" => { + request_fs_command_init(&mut request); + request.fs_command.as_mut().unwrap().left = Some(arg_from_str(value.unwrap_or("-0"), err, "fs-command.left", "integer")); + }, + "rendering-id-dimension-value.kind" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.value" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.dimension-name" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.etag" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.match-type" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "rendering-id-dimension-value.id" => { + request_rendering_id_dimension_value_init(&mut request); + request.rendering_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_rendering_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "size.width" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().width = Some(arg_from_str(value.unwrap_or("-0"), err, "size.width", "integer")); + }, + "size.kind" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "size.iab" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().iab = Some(arg_from_str(value.unwrap_or("false"), err, "size.iab", "boolean")); + }, + "size.id" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.height" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().height = Some(arg_from_str(value.unwrap_or("-0"), err, "size.height", "integer")); + }, + "studio-trafficked-creative-id" => { + request_size_init(&mut request); + request.studio_trafficked_creative_id = Some(value.unwrap_or("").to_string()); + }, + "archived" => { + request_size_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "override-css" => { + request_size_init(&mut request); + request.override_css = Some(value.unwrap_or("").to_string()); + }, + "required-flash-version" => { + request_size_init(&mut request); + request.required_flash_version = Some(arg_from_str(value.unwrap_or("-0"), err, "required-flash-version", "integer")); + }, + "rendering-id" => { + request_size_init(&mut request); + request.rendering_id = Some(value.unwrap_or("").to_string()); + }, + "video-description" => { + request_size_init(&mut request); + request.video_description = Some(value.unwrap_or("").to_string()); + }, + "third-party-backup-image-impressions-url" => { + request_size_init(&mut request); + request.third_party_backup_image_impressions_url = Some(value.unwrap_or("").to_string()); + }, + "version" => { + request_size_init(&mut request); + request.version = Some(arg_from_str(value.unwrap_or("-0"), err, "version", "integer")); + }, + "background-color" => { + request_size_init(&mut request); + request.background_color = Some(value.unwrap_or("").to_string()); + }, + "custom-key-values" => { + request_size_init(&mut request); + if request.custom_key_values.is_none() { + request.custom_key_values = Some(Default::default()); + } + request.custom_key_values.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "html-code" => { + request_id_dimension_value_init(&mut request); + request.html_code = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "type" => { + request_id_dimension_value_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "total-file-size" => { + request_id_dimension_value_init(&mut request); + request.total_file_size = Some(value.unwrap_or("").to_string()); + }, + "third-party-rich-media-impressions-url" => { + request_id_dimension_value_init(&mut request); + request.third_party_rich_media_impressions_url = Some(value.unwrap_or("").to_string()); + }, + "studio-advertiser-id" => { + request_id_dimension_value_init(&mut request); + request.studio_advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "html-code-locked" => { + request_id_dimension_value_init(&mut request); + request.html_code_locked = Some(arg_from_str(value.unwrap_or("false"), err, "html-code-locked", "boolean")); + }, + "redirect-url" => { + request_id_dimension_value_init(&mut request); + request.redirect_url = Some(value.unwrap_or("").to_string()); + }, + "commercial-id" => { + request_id_dimension_value_init(&mut request); + request.commercial_id = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_id_dimension_value_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "backup-image-reporting-label" => { + request_id_dimension_value_init(&mut request); + request.backup_image_reporting_label = Some(value.unwrap_or("").to_string()); + }, + "compatibility" => { + request_id_dimension_value_init(&mut request); + if request.compatibility.is_none() { + request.compatibility = Some(Default::default()); + } + request.compatibility.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "ad-parameters" => { + request_id_dimension_value_init(&mut request); + request.ad_parameters = Some(value.unwrap_or("").to_string()); + }, + "ad-tag-keys" => { + request_id_dimension_value_init(&mut request); + if request.ad_tag_keys.is_none() { + request.ad_tag_keys = Some(Default::default()); + } + request.ad_tag_keys.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "kind" => { + request_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_id_dimension_value_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_id_dimension_value_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "convert-flash-to-html5" => { + request_id_dimension_value_init(&mut request); + request.convert_flash_to_html5 = Some(arg_from_str(value.unwrap_or("false"), err, "convert-flash-to-html5", "boolean")); + }, + "video-duration" => { + request_id_dimension_value_init(&mut request); + request.video_duration = Some(arg_from_str(value.unwrap_or("0.0"), err, "video-duration", "number")); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "backup-image-click-through-url" => { + request_last_modified_info_init(&mut request); + request.backup_image_click_through_url = Some(value.unwrap_or("").to_string()); + }, + "ssl-compliant" => { + request_last_modified_info_init(&mut request); + request.ssl_compliant = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-compliant", "boolean")); + }, + "studio-creative-id" => { + request_last_modified_info_init(&mut request); + request.studio_creative_id = Some(value.unwrap_or("").to_string()); + }, + "authoring-tool" => { + request_last_modified_info_init(&mut request); + request.authoring_tool = Some(value.unwrap_or("").to_string()); + }, + "allow-script-access" => { + request_last_modified_info_init(&mut request); + request.allow_script_access = Some(arg_from_str(value.unwrap_or("false"), err, "allow-script-access", "boolean")); + }, + "companion-creatives" => { + request_last_modified_info_init(&mut request); + if request.companion_creatives.is_none() { + request.companion_creatives = Some(Default::default()); + } + request.companion_creatives.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "auto-advance-images" => { + request_last_modified_info_init(&mut request); + request.auto_advance_images = Some(arg_from_str(value.unwrap_or("false"), err, "auto-advance-images", "boolean")); + }, + "backup-image-features" => { + request_last_modified_info_init(&mut request); + if request.backup_image_features.is_none() { + request.backup_image_features = Some(Default::default()); + } + request.backup_image_features.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "backup-image-target-window.custom-html" => { + request_backup_image_target_window_init(&mut request); + request.backup_image_target_window.as_mut().unwrap().custom_html = Some(value.unwrap_or("").to_string()); + }, + "backup-image-target-window.target-window-option" => { + request_backup_image_target_window_init(&mut request); + request.backup_image_target_window.as_mut().unwrap().target_window_option = Some(value.unwrap_or("").to_string()); + }, + "skippable" => { + request_backup_image_target_window_init(&mut request); + request.skippable = Some(arg_from_str(value.unwrap_or("false"), err, "skippable", "boolean")); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "ad-parameters", "ad-tag-keys", "advertiser-id", "allow-script-access", "archived", "artwork-type", "authoring-tool", "auto-advance-images", "background-color", "backup-image-click-through-url", "backup-image-features", "backup-image-reporting-label", "backup-image-target-window", "commercial-id", "companion-creatives", "compatibility", "convert-flash-to-html5", "custom-html", "custom-key-values", "dimension-name", "etag", "fs-command", "height", "html-code", "html-code-locked", "iab", "id", "id-dimension-value", "kind", "last-modified-info", "latest-trafficked-creative-id", "left", "match-type", "name", "override-css", "position-option", "redirect-url", "rendering-id", "rendering-id-dimension-value", "required-flash-plugin-version", "required-flash-version", "size", "skippable", "ssl-compliant", "studio-advertiser-id", "studio-creative-id", "studio-trafficked-creative-id", "subaccount-id", "target-window-option", "third-party-backup-image-impressions-url", "third-party-rich-media-impressions-url", "time", "top", "total-file-size", "type", "value", "version", "video-description", "video-duration", "width", "window-height", "window-width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.creatives().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _dimension_values_query(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::DimensionValueRequest::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "dimension-name" => { + request.dimension_name = Some(value.unwrap_or("").to_string()); + }, + "start-date" => { + request.start_date = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "end-date" => { + request.end_date = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["dimension-name", "end-date", "kind", "start-date"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.dimension_values().query(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _directory_site_contacts_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.directory_site_contacts().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _directory_site_contacts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.directory_site_contacts().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "directory-site-ids" => { + call = call.add_directory_site_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "directory-site-ids", "sort-field", "ids", "max-results", "page-token", "sort-order"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _directory_sites_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.directory_sites().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _directory_sites_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::DirectorySite::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_id_dimension_value_init(request: &mut api::DirectorySite) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_settings_dfp_settings_init(request: &mut api::DirectorySite) { + request_settings_init(request); + if request.settings.as_mut().unwrap().dfp_settings.is_none() { + request.settings.as_mut().unwrap().dfp_settings = Some(Default::default()); + } + } + + fn request_settings_init(request: &mut api::DirectorySite) { + if request.settings.is_none() { + request.settings = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "country-id" => { + request.country_id = Some(value.unwrap_or("").to_string()); + }, + "description" => { + request.description = Some(value.unwrap_or("").to_string()); + }, + "settings.nielsen-ocr-opt-out" => { + request_settings_init(&mut request); + request.settings.as_mut().unwrap().nielsen_ocr_opt_out = Some(arg_from_str(value.unwrap_or("false"), err, "settings.nielsen-ocr-opt-out", "boolean")); + }, + "settings.active-view-opt-out" => { + request_settings_init(&mut request); + request.settings.as_mut().unwrap().active_view_opt_out = Some(arg_from_str(value.unwrap_or("false"), err, "settings.active-view-opt-out", "boolean")); + }, + "settings.dfp-settings.dfp-network-name" => { + request_settings_dfp_settings_init(&mut request); + request.settings.as_mut().unwrap().dfp_settings.as_mut().unwrap().dfp_network_name = Some(value.unwrap_or("").to_string()); + }, + "settings.dfp-settings.publisher-portal-only" => { + request_settings_dfp_settings_init(&mut request); + request.settings.as_mut().unwrap().dfp_settings.as_mut().unwrap().publisher_portal_only = Some(arg_from_str(value.unwrap_or("false"), err, "settings.dfp-settings.publisher-portal-only", "boolean")); + }, + "settings.dfp-settings.programmatic-placement-accepted" => { + request_settings_dfp_settings_init(&mut request); + request.settings.as_mut().unwrap().dfp_settings.as_mut().unwrap().programmatic_placement_accepted = Some(arg_from_str(value.unwrap_or("false"), err, "settings.dfp-settings.programmatic-placement-accepted", "boolean")); + }, + "settings.dfp-settings.pub-paid-placement-accepted" => { + request_settings_dfp_settings_init(&mut request); + request.settings.as_mut().unwrap().dfp_settings.as_mut().unwrap().pub_paid_placement_accepted = Some(arg_from_str(value.unwrap_or("false"), err, "settings.dfp-settings.pub-paid-placement-accepted", "boolean")); + }, + "settings.dfp-settings.dfp-network-code" => { + request_settings_dfp_settings_init(&mut request); + request.settings.as_mut().unwrap().dfp_settings.as_mut().unwrap().dfp_network_code = Some(value.unwrap_or("").to_string()); + }, + "settings.verification-tag-opt-out" => { + request_settings_dfp_settings_init(&mut request); + request.settings.as_mut().unwrap().verification_tag_opt_out = Some(arg_from_str(value.unwrap_or("false"), err, "settings.verification-tag-opt-out", "boolean")); + }, + "settings.instream-video-placement-accepted" => { + request_settings_dfp_settings_init(&mut request); + request.settings.as_mut().unwrap().instream_video_placement_accepted = Some(arg_from_str(value.unwrap_or("false"), err, "settings.instream-video-placement-accepted", "boolean")); + }, + "settings.interstitial-placement-accepted" => { + request_settings_dfp_settings_init(&mut request); + request.settings.as_mut().unwrap().interstitial_placement_accepted = Some(arg_from_str(value.unwrap_or("false"), err, "settings.interstitial-placement-accepted", "boolean")); + }, + "settings.video-active-view-opt-out" => { + request_settings_dfp_settings_init(&mut request); + request.settings.as_mut().unwrap().video_active_view_opt_out = Some(arg_from_str(value.unwrap_or("false"), err, "settings.video-active-view-opt-out", "boolean")); + }, + "currency-id" => { + request_settings_init(&mut request); + request.currency_id = Some(value.unwrap_or("").to_string()); + }, + "inpage-tag-formats" => { + request_settings_init(&mut request); + if request.inpage_tag_formats.is_none() { + request.inpage_tag_formats = Some(Default::default()); + } + request.inpage_tag_formats.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "url" => { + request_settings_init(&mut request); + request.url = Some(value.unwrap_or("").to_string()); + }, + "parent-id" => { + request_settings_init(&mut request); + request.parent_id = Some(value.unwrap_or("").to_string()); + }, + "interstitial-tag-formats" => { + request_settings_init(&mut request); + if request.interstitial_tag_formats.is_none() { + request.interstitial_tag_formats = Some(Default::default()); + } + request.interstitial_tag_formats.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_id_dimension_value_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "id" => { + request_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_id_dimension_value_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["active", "active-view-opt-out", "country-id", "currency-id", "description", "dfp-network-code", "dfp-network-name", "dfp-settings", "dimension-name", "etag", "id", "id-dimension-value", "inpage-tag-formats", "instream-video-placement-accepted", "interstitial-placement-accepted", "interstitial-tag-formats", "kind", "match-type", "name", "nielsen-ocr-opt-out", "parent-id", "programmatic-placement-accepted", "pub-paid-placement-accepted", "publisher-portal-only", "settings", "url", "value", "verification-tag-opt-out", "video-active-view-opt-out"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.directory_sites().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _directory_sites_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.directory_sites().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "parent-id" => { + call = call.parent_id(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "dfp-network-code" => { + call = call.dfp_network_code(value.unwrap_or("")); + }, + "country-id" => { + call = call.country_id(value.unwrap_or("")); + }, + "active" => { + call = call.active(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "accepts-publisher-paid-placements" => { + call = call.accepts_publisher_paid_placements(arg_from_str(value.unwrap_or("false"), err, "accepts-publisher-paid-placements", "boolean")); + }, + "accepts-interstitial-placements" => { + call = call.accepts_interstitial_placements(arg_from_str(value.unwrap_or("false"), err, "accepts-interstitial-placements", "boolean")); + }, + "accepts-in-stream-video-placements" => { + call = call.accepts_in_stream_video_placements(arg_from_str(value.unwrap_or("false"), err, "accepts-in-stream-video-placements", "boolean")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["accepts-interstitial-placements", "accepts-publisher-paid-placements", "search-string", "country-id", "accepts-in-stream-video-placements", "sort-field", "ids", "max-results", "page-token", "sort-order", "parent-id", "active", "dfp-network-code"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _event_tags_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.event_tags().delete(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _event_tags_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.event_tags().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _event_tags_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::EventTag::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::EventTag) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_campaign_id_dimension_value_init(request: &mut api::EventTag) { + if request.campaign_id_dimension_value.is_none() { + request.campaign_id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "status" => { + request.status = Some(value.unwrap_or("").to_string()); + }, + "site-ids" => { + if request.site_ids.is_none() { + request.site_ids = Some(Default::default()); + } + request.site_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id" => { + request.campaign_id = Some(value.unwrap_or("").to_string()); + }, + "url" => { + request.url = Some(value.unwrap_or("").to_string()); + }, + "ssl-compliant" => { + request.ssl_compliant = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-compliant", "boolean")); + }, + "url-escape-levels" => { + request.url_escape_levels = Some(arg_from_str(value.unwrap_or("-0"), err, "url-escape-levels", "integer")); + }, + "campaign-id-dimension-value.kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.value" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.dimension-name" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.etag" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.match-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.id" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "enabled-by-default" => { + request_campaign_id_dimension_value_init(&mut request); + request.enabled_by_default = Some(arg_from_str(value.unwrap_or("false"), err, "enabled-by-default", "boolean")); + }, + "advertiser-id" => { + request_campaign_id_dimension_value_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "site-filter-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.site_filter_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "campaign-id", "campaign-id-dimension-value", "dimension-name", "enabled-by-default", "etag", "id", "kind", "match-type", "name", "site-filter-type", "site-ids", "ssl-compliant", "status", "subaccount-id", "type", "url", "url-escape-levels", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.event_tags().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _event_tags_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.event_tags().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "event-tag-types" => { + call = call.add_event_tag_types(value.unwrap_or("")); + }, + "enabled" => { + call = call.enabled(arg_from_str(value.unwrap_or("false"), err, "enabled", "boolean")); + }, + "definitions-only" => { + call = call.definitions_only(arg_from_str(value.unwrap_or("false"), err, "definitions-only", "boolean")); + }, + "campaign-id" => { + call = call.campaign_id(value.unwrap_or("")); + }, + "advertiser-id" => { + call = call.advertiser_id(value.unwrap_or("")); + }, + "ad-id" => { + call = call.ad_id(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "campaign-id", "sort-field", "enabled", "ids", "advertiser-id", "ad-id", "sort-order", "event-tag-types", "definitions-only"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _event_tags_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::EventTag::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::EventTag) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_campaign_id_dimension_value_init(request: &mut api::EventTag) { + if request.campaign_id_dimension_value.is_none() { + request.campaign_id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "status" => { + request.status = Some(value.unwrap_or("").to_string()); + }, + "site-ids" => { + if request.site_ids.is_none() { + request.site_ids = Some(Default::default()); + } + request.site_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id" => { + request.campaign_id = Some(value.unwrap_or("").to_string()); + }, + "url" => { + request.url = Some(value.unwrap_or("").to_string()); + }, + "ssl-compliant" => { + request.ssl_compliant = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-compliant", "boolean")); + }, + "url-escape-levels" => { + request.url_escape_levels = Some(arg_from_str(value.unwrap_or("-0"), err, "url-escape-levels", "integer")); + }, + "campaign-id-dimension-value.kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.value" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.dimension-name" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.etag" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.match-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.id" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "enabled-by-default" => { + request_campaign_id_dimension_value_init(&mut request); + request.enabled_by_default = Some(arg_from_str(value.unwrap_or("false"), err, "enabled-by-default", "boolean")); + }, + "advertiser-id" => { + request_campaign_id_dimension_value_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "site-filter-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.site_filter_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "campaign-id", "campaign-id-dimension-value", "dimension-name", "enabled-by-default", "etag", "id", "kind", "match-type", "name", "site-filter-type", "site-ids", "ssl-compliant", "status", "subaccount-id", "type", "url", "url-escape-levels", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.event_tags().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _event_tags_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::EventTag::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::EventTag) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_campaign_id_dimension_value_init(request: &mut api::EventTag) { + if request.campaign_id_dimension_value.is_none() { + request.campaign_id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "status" => { + request.status = Some(value.unwrap_or("").to_string()); + }, + "site-ids" => { + if request.site_ids.is_none() { + request.site_ids = Some(Default::default()); + } + request.site_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id" => { + request.campaign_id = Some(value.unwrap_or("").to_string()); + }, + "url" => { + request.url = Some(value.unwrap_or("").to_string()); + }, + "ssl-compliant" => { + request.ssl_compliant = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-compliant", "boolean")); + }, + "url-escape-levels" => { + request.url_escape_levels = Some(arg_from_str(value.unwrap_or("-0"), err, "url-escape-levels", "integer")); + }, + "campaign-id-dimension-value.kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.value" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.dimension-name" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.etag" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.match-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.id" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "enabled-by-default" => { + request_campaign_id_dimension_value_init(&mut request); + request.enabled_by_default = Some(arg_from_str(value.unwrap_or("false"), err, "enabled-by-default", "boolean")); + }, + "advertiser-id" => { + request_campaign_id_dimension_value_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "site-filter-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.site_filter_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "campaign-id", "campaign-id-dimension-value", "dimension-name", "enabled-by-default", "etag", "id", "kind", "match-type", "name", "site-filter-type", "site-ids", "ssl-compliant", "status", "subaccount-id", "type", "url", "url-escape-levels", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.event_tags().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _files_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut download_mode = false; + let mut call = self.hub.files().get(opt.value_of("report-id").unwrap_or(""), opt.value_of("file-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + if !download_mode { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + } else { + io::copy(&mut response, &mut ostream).unwrap(); + } + Ok(()) + } + } + } + } + + fn _files_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.files().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "scope" => { + call = call.scope(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sort-field", "max-results", "sort-order", "page-token", "scope"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_activities_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.floodlight_activities().delete(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _floodlight_activities_generatetag(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.floodlight_activities().generatetag(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "floodlight-activity-id" => { + call = call.floodlight_activity_id(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["floodlight-activity-id"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_activities_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.floodlight_activities().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_activities_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::FloodlightActivity::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::FloodlightActivity) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_floodlight_configuration_id_dimension_value_init(request: &mut api::FloodlightActivity) { + if request.floodlight_configuration_id_dimension_value.is_none() { + request.floodlight_configuration_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::FloodlightActivity) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "tag-string" => { + request.tag_string = Some(value.unwrap_or("").to_string()); + }, + "secure" => { + request.secure = Some(arg_from_str(value.unwrap_or("false"), err, "secure", "boolean")); + }, + "floodlight-activity-group-name" => { + request.floodlight_activity_group_name = Some(value.unwrap_or("").to_string()); + }, + "image-tag-enabled" => { + request.image_tag_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "image-tag-enabled", "boolean")); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-activity-group-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.floodlight_activity_group_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-activity-group-tag-string" => { + request_advertiser_id_dimension_value_init(&mut request); + request.floodlight_activity_group_tag_string = Some(value.unwrap_or("").to_string()); + }, + "ssl-compliant" => { + request_advertiser_id_dimension_value_init(&mut request); + request.ssl_compliant = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-compliant", "boolean")); + }, + "floodlight-configuration-id-dimension-value.kind" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.value" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.dimension-name" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.etag" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.match-type" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "cache-busting-type" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.cache_busting_type = Some(value.unwrap_or("").to_string()); + }, + "hidden" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.hidden = Some(arg_from_str(value.unwrap_or("false"), err, "hidden", "boolean")); + }, + "account-id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "ssl-required" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.ssl_required = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-required", "boolean")); + }, + "expected-url" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.expected_url = Some(value.unwrap_or("").to_string()); + }, + "tag-format" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.tag_format = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "notes" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.notes = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "user-defined-variable-types" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + if request.user_defined_variable_types.is_none() { + request.user_defined_variable_types = Some(Default::default()); + } + request.user_defined_variable_types.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "counting-method" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.counting_method = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-activity-group-type" => { + request_id_dimension_value_init(&mut request); + request.floodlight_activity_group_type = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "cache-busting-type", "counting-method", "dimension-name", "etag", "expected-url", "floodlight-activity-group-id", "floodlight-activity-group-name", "floodlight-activity-group-tag-string", "floodlight-activity-group-type", "floodlight-configuration-id", "floodlight-configuration-id-dimension-value", "hidden", "id", "id-dimension-value", "image-tag-enabled", "kind", "match-type", "name", "notes", "secure", "ssl-compliant", "ssl-required", "subaccount-id", "tag-format", "tag-string", "user-defined-variable-types", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.floodlight_activities().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_activities_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.floodlight_activities().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "tag-string" => { + call = call.tag_string(value.unwrap_or("")); + }, + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "floodlight-configuration-id" => { + call = call.floodlight_configuration_id(value.unwrap_or("")); + }, + "floodlight-activity-group-type" => { + call = call.floodlight_activity_group_type(value.unwrap_or("")); + }, + "floodlight-activity-group-tag-string" => { + call = call.floodlight_activity_group_tag_string(value.unwrap_or("")); + }, + "floodlight-activity-group-name" => { + call = call.floodlight_activity_group_name(value.unwrap_or("")); + }, + "floodlight-activity-group-ids" => { + call = call.add_floodlight_activity_group_ids(value.unwrap_or("")); + }, + "advertiser-id" => { + call = call.advertiser_id(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["floodlight-activity-group-ids", "search-string", "floodlight-activity-group-name", "sort-field", "floodlight-configuration-id", "ids", "max-results", "advertiser-id", "page-token", "sort-order", "tag-string", "floodlight-activity-group-tag-string", "floodlight-activity-group-type"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_activities_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::FloodlightActivity::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::FloodlightActivity) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_floodlight_configuration_id_dimension_value_init(request: &mut api::FloodlightActivity) { + if request.floodlight_configuration_id_dimension_value.is_none() { + request.floodlight_configuration_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::FloodlightActivity) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "tag-string" => { + request.tag_string = Some(value.unwrap_or("").to_string()); + }, + "secure" => { + request.secure = Some(arg_from_str(value.unwrap_or("false"), err, "secure", "boolean")); + }, + "floodlight-activity-group-name" => { + request.floodlight_activity_group_name = Some(value.unwrap_or("").to_string()); + }, + "image-tag-enabled" => { + request.image_tag_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "image-tag-enabled", "boolean")); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-activity-group-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.floodlight_activity_group_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-activity-group-tag-string" => { + request_advertiser_id_dimension_value_init(&mut request); + request.floodlight_activity_group_tag_string = Some(value.unwrap_or("").to_string()); + }, + "ssl-compliant" => { + request_advertiser_id_dimension_value_init(&mut request); + request.ssl_compliant = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-compliant", "boolean")); + }, + "floodlight-configuration-id-dimension-value.kind" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.value" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.dimension-name" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.etag" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.match-type" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "cache-busting-type" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.cache_busting_type = Some(value.unwrap_or("").to_string()); + }, + "hidden" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.hidden = Some(arg_from_str(value.unwrap_or("false"), err, "hidden", "boolean")); + }, + "account-id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "ssl-required" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.ssl_required = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-required", "boolean")); + }, + "expected-url" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.expected_url = Some(value.unwrap_or("").to_string()); + }, + "tag-format" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.tag_format = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "notes" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.notes = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "user-defined-variable-types" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + if request.user_defined_variable_types.is_none() { + request.user_defined_variable_types = Some(Default::default()); + } + request.user_defined_variable_types.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "counting-method" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.counting_method = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-activity-group-type" => { + request_id_dimension_value_init(&mut request); + request.floodlight_activity_group_type = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "cache-busting-type", "counting-method", "dimension-name", "etag", "expected-url", "floodlight-activity-group-id", "floodlight-activity-group-name", "floodlight-activity-group-tag-string", "floodlight-activity-group-type", "floodlight-configuration-id", "floodlight-configuration-id-dimension-value", "hidden", "id", "id-dimension-value", "image-tag-enabled", "kind", "match-type", "name", "notes", "secure", "ssl-compliant", "ssl-required", "subaccount-id", "tag-format", "tag-string", "user-defined-variable-types", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.floodlight_activities().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_activities_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::FloodlightActivity::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::FloodlightActivity) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_floodlight_configuration_id_dimension_value_init(request: &mut api::FloodlightActivity) { + if request.floodlight_configuration_id_dimension_value.is_none() { + request.floodlight_configuration_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::FloodlightActivity) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "tag-string" => { + request.tag_string = Some(value.unwrap_or("").to_string()); + }, + "secure" => { + request.secure = Some(arg_from_str(value.unwrap_or("false"), err, "secure", "boolean")); + }, + "floodlight-activity-group-name" => { + request.floodlight_activity_group_name = Some(value.unwrap_or("").to_string()); + }, + "image-tag-enabled" => { + request.image_tag_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "image-tag-enabled", "boolean")); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-activity-group-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.floodlight_activity_group_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-activity-group-tag-string" => { + request_advertiser_id_dimension_value_init(&mut request); + request.floodlight_activity_group_tag_string = Some(value.unwrap_or("").to_string()); + }, + "ssl-compliant" => { + request_advertiser_id_dimension_value_init(&mut request); + request.ssl_compliant = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-compliant", "boolean")); + }, + "floodlight-configuration-id-dimension-value.kind" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.value" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.dimension-name" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.etag" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.match-type" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "cache-busting-type" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.cache_busting_type = Some(value.unwrap_or("").to_string()); + }, + "hidden" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.hidden = Some(arg_from_str(value.unwrap_or("false"), err, "hidden", "boolean")); + }, + "account-id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "ssl-required" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.ssl_required = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-required", "boolean")); + }, + "expected-url" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.expected_url = Some(value.unwrap_or("").to_string()); + }, + "tag-format" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.tag_format = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "notes" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.notes = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "user-defined-variable-types" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + if request.user_defined_variable_types.is_none() { + request.user_defined_variable_types = Some(Default::default()); + } + request.user_defined_variable_types.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "counting-method" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.counting_method = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-activity-group-type" => { + request_id_dimension_value_init(&mut request); + request.floodlight_activity_group_type = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "cache-busting-type", "counting-method", "dimension-name", "etag", "expected-url", "floodlight-activity-group-id", "floodlight-activity-group-name", "floodlight-activity-group-tag-string", "floodlight-activity-group-type", "floodlight-configuration-id", "floodlight-configuration-id-dimension-value", "hidden", "id", "id-dimension-value", "image-tag-enabled", "kind", "match-type", "name", "notes", "secure", "ssl-compliant", "ssl-required", "subaccount-id", "tag-format", "tag-string", "user-defined-variable-types", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.floodlight_activities().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_activity_groups_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.floodlight_activity_groups().delete(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _floodlight_activity_groups_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.floodlight_activity_groups().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_activity_groups_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::FloodlightActivityGroup::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::FloodlightActivityGroup) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_floodlight_configuration_id_dimension_value_init(request: &mut api::FloodlightActivityGroup) { + if request.floodlight_configuration_id_dimension_value.is_none() { + request.floodlight_configuration_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::FloodlightActivityGroup) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id" => { + request.floodlight_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.kind" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.value" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.dimension-name" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.etag" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.match-type" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "tag-string" => { + request_advertiser_id_dimension_value_init(&mut request); + request.tag_string = Some(value.unwrap_or("").to_string()); + }, + "type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "dimension-name", "etag", "floodlight-configuration-id", "floodlight-configuration-id-dimension-value", "id", "id-dimension-value", "kind", "match-type", "name", "subaccount-id", "tag-string", "type", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.floodlight_activity_groups().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_activity_groups_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.floodlight_activity_groups().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "type" => { + call = call.type_(value.unwrap_or("")); + }, + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "floodlight-configuration-id" => { + call = call.floodlight_configuration_id(value.unwrap_or("")); + }, + "advertiser-id" => { + call = call.advertiser_id(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "sort-field", "floodlight-configuration-id", "ids", "max-results", "advertiser-id", "page-token", "sort-order", "type"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_activity_groups_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::FloodlightActivityGroup::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::FloodlightActivityGroup) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_floodlight_configuration_id_dimension_value_init(request: &mut api::FloodlightActivityGroup) { + if request.floodlight_configuration_id_dimension_value.is_none() { + request.floodlight_configuration_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::FloodlightActivityGroup) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id" => { + request.floodlight_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.kind" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.value" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.dimension-name" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.etag" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.match-type" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "tag-string" => { + request_advertiser_id_dimension_value_init(&mut request); + request.tag_string = Some(value.unwrap_or("").to_string()); + }, + "type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "dimension-name", "etag", "floodlight-configuration-id", "floodlight-configuration-id-dimension-value", "id", "id-dimension-value", "kind", "match-type", "name", "subaccount-id", "tag-string", "type", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.floodlight_activity_groups().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_activity_groups_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::FloodlightActivityGroup::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::FloodlightActivityGroup) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_floodlight_configuration_id_dimension_value_init(request: &mut api::FloodlightActivityGroup) { + if request.floodlight_configuration_id_dimension_value.is_none() { + request.floodlight_configuration_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::FloodlightActivityGroup) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id" => { + request.floodlight_configuration_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.kind" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.value" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.dimension-name" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.etag" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.match-type" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "floodlight-configuration-id-dimension-value.id" => { + request_floodlight_configuration_id_dimension_value_init(&mut request); + request.floodlight_configuration_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "tag-string" => { + request_advertiser_id_dimension_value_init(&mut request); + request.tag_string = Some(value.unwrap_or("").to_string()); + }, + "type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "dimension-name", "etag", "floodlight-configuration-id", "floodlight-configuration-id-dimension-value", "id", "id-dimension-value", "kind", "match-type", "name", "subaccount-id", "tag-string", "type", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.floodlight_activity_groups().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_configurations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.floodlight_configurations().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_configurations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.floodlight_configurations().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["ids"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_configurations_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::FloodlightConfiguration::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::FloodlightConfiguration) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::FloodlightConfiguration) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_lookback_configuration_init(request: &mut api::FloodlightConfiguration) { + if request.lookback_configuration.is_none() { + request.lookback_configuration = Some(Default::default()); + } + } + + fn request_omniture_settings_init(request: &mut api::FloodlightConfiguration) { + if request.omniture_settings.is_none() { + request.omniture_settings = Some(Default::default()); + } + } + + fn request_tag_settings_init(request: &mut api::FloodlightConfiguration) { + if request.tag_settings.is_none() { + request.tag_settings = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "natural-search-conversion-attribution-option" => { + request.natural_search_conversion_attribution_option = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "exposure-to-conversion-enabled" => { + request.exposure_to_conversion_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "exposure-to-conversion-enabled", "boolean")); + }, + "analytics-data-sharing-enabled" => { + request.analytics_data_sharing_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "analytics-data-sharing-enabled", "boolean")); + }, + "lookback-configuration.click-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().click_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.click-duration", "integer")); + }, + "lookback-configuration.post-impression-activities-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().post_impression_activities_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.post-impression-activities-duration", "integer")); + }, + "first-day-of-week" => { + request_lookback_configuration_init(&mut request); + request.first_day_of_week = Some(value.unwrap_or("").to_string()); + }, + "standard-variable-types" => { + request_lookback_configuration_init(&mut request); + if request.standard_variable_types.is_none() { + request.standard_variable_types = Some(Default::default()); + } + request.standard_variable_types.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "omniture-settings.omniture-cost-data-enabled" => { + request_omniture_settings_init(&mut request); + request.omniture_settings.as_mut().unwrap().omniture_cost_data_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "omniture-settings.omniture-cost-data-enabled", "boolean")); + }, + "omniture-settings.omniture-integration-enabled" => { + request_omniture_settings_init(&mut request); + request.omniture_settings.as_mut().unwrap().omniture_integration_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "omniture-settings.omniture-integration-enabled", "boolean")); + }, + "subaccount-id" => { + request_omniture_settings_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request_omniture_settings_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "tag-settings.dynamic-tag-enabled" => { + request_tag_settings_init(&mut request); + request.tag_settings.as_mut().unwrap().dynamic_tag_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "tag-settings.dynamic-tag-enabled", "boolean")); + }, + "tag-settings.image-tag-enabled" => { + request_tag_settings_init(&mut request); + request.tag_settings.as_mut().unwrap().image_tag_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "tag-settings.image-tag-enabled", "boolean")); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "ssl-required" => { + request_advertiser_id_dimension_value_init(&mut request); + request.ssl_required = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-required", "boolean")); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "analytics-data-sharing-enabled", "click-duration", "dimension-name", "dynamic-tag-enabled", "etag", "exposure-to-conversion-enabled", "first-day-of-week", "id", "id-dimension-value", "image-tag-enabled", "kind", "lookback-configuration", "match-type", "natural-search-conversion-attribution-option", "omniture-cost-data-enabled", "omniture-integration-enabled", "omniture-settings", "post-impression-activities-duration", "ssl-required", "standard-variable-types", "subaccount-id", "tag-settings", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.floodlight_configurations().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _floodlight_configurations_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::FloodlightConfiguration::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::FloodlightConfiguration) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::FloodlightConfiguration) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_lookback_configuration_init(request: &mut api::FloodlightConfiguration) { + if request.lookback_configuration.is_none() { + request.lookback_configuration = Some(Default::default()); + } + } + + fn request_omniture_settings_init(request: &mut api::FloodlightConfiguration) { + if request.omniture_settings.is_none() { + request.omniture_settings = Some(Default::default()); + } + } + + fn request_tag_settings_init(request: &mut api::FloodlightConfiguration) { + if request.tag_settings.is_none() { + request.tag_settings = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "natural-search-conversion-attribution-option" => { + request.natural_search_conversion_attribution_option = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "exposure-to-conversion-enabled" => { + request.exposure_to_conversion_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "exposure-to-conversion-enabled", "boolean")); + }, + "analytics-data-sharing-enabled" => { + request.analytics_data_sharing_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "analytics-data-sharing-enabled", "boolean")); + }, + "lookback-configuration.click-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().click_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.click-duration", "integer")); + }, + "lookback-configuration.post-impression-activities-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().post_impression_activities_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.post-impression-activities-duration", "integer")); + }, + "first-day-of-week" => { + request_lookback_configuration_init(&mut request); + request.first_day_of_week = Some(value.unwrap_or("").to_string()); + }, + "standard-variable-types" => { + request_lookback_configuration_init(&mut request); + if request.standard_variable_types.is_none() { + request.standard_variable_types = Some(Default::default()); + } + request.standard_variable_types.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "omniture-settings.omniture-cost-data-enabled" => { + request_omniture_settings_init(&mut request); + request.omniture_settings.as_mut().unwrap().omniture_cost_data_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "omniture-settings.omniture-cost-data-enabled", "boolean")); + }, + "omniture-settings.omniture-integration-enabled" => { + request_omniture_settings_init(&mut request); + request.omniture_settings.as_mut().unwrap().omniture_integration_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "omniture-settings.omniture-integration-enabled", "boolean")); + }, + "subaccount-id" => { + request_omniture_settings_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request_omniture_settings_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "tag-settings.dynamic-tag-enabled" => { + request_tag_settings_init(&mut request); + request.tag_settings.as_mut().unwrap().dynamic_tag_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "tag-settings.dynamic-tag-enabled", "boolean")); + }, + "tag-settings.image-tag-enabled" => { + request_tag_settings_init(&mut request); + request.tag_settings.as_mut().unwrap().image_tag_enabled = Some(arg_from_str(value.unwrap_or("false"), err, "tag-settings.image-tag-enabled", "boolean")); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "ssl-required" => { + request_advertiser_id_dimension_value_init(&mut request); + request.ssl_required = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-required", "boolean")); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "analytics-data-sharing-enabled", "click-duration", "dimension-name", "dynamic-tag-enabled", "etag", "exposure-to-conversion-enabled", "first-day-of-week", "id", "id-dimension-value", "image-tag-enabled", "kind", "lookback-configuration", "match-type", "natural-search-conversion-attribution-option", "omniture-cost-data-enabled", "omniture-integration-enabled", "omniture-settings", "post-impression-activities-duration", "ssl-required", "standard-variable-types", "subaccount-id", "tag-settings", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.floodlight_configurations().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _inventory_items_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.inventory_items().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("project-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _inventory_items_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.inventory_items().list(opt.value_of("profile-id").unwrap_or(""), opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "site-id" => { + call = call.add_site_id(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "order-id" => { + call = call.add_order_id(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "in-plan" => { + call = call.in_plan(arg_from_str(value.unwrap_or("false"), err, "in-plan", "boolean")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["order-id", "sort-field", "ids", "max-results", "page-token", "in-plan", "site-id", "sort-order"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _landing_pages_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.landing_pages().delete(opt.value_of("profile-id").unwrap_or(""), opt.value_of("campaign-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _landing_pages_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.landing_pages().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("campaign-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _landing_pages_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::LandingPage::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "default" => { + request.default = Some(arg_from_str(value.unwrap_or("false"), err, "default", "boolean")); + }, + "url" => { + request.url = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["default", "id", "kind", "name", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.landing_pages().insert(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("campaign-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _landing_pages_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.landing_pages().list(opt.value_of("profile-id").unwrap_or(""), opt.value_of("campaign-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _landing_pages_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::LandingPage::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "default" => { + request.default = Some(arg_from_str(value.unwrap_or("false"), err, "default", "boolean")); + }, + "url" => { + request.url = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["default", "id", "kind", "name", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.landing_pages().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("campaign-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _landing_pages_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::LandingPage::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "default" => { + request.default = Some(arg_from_str(value.unwrap_or("false"), err, "default", "boolean")); + }, + "url" => { + request.url = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["default", "id", "kind", "name", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.landing_pages().update(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("campaign-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _metros_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.metros().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _mobile_carriers_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.mobile_carriers().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _mobile_carriers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.mobile_carriers().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _operating_system_versions_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.operating_system_versions().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _operating_system_versions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.operating_system_versions().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _operating_systems_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.operating_systems().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("dart-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _operating_systems_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.operating_systems().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _order_documents_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.order_documents().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("project-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _order_documents_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.order_documents().list(opt.value_of("profile-id").unwrap_or(""), opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "site-id" => { + call = call.add_site_id(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "order-id" => { + call = call.add_order_id(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "approved" => { + call = call.approved(arg_from_str(value.unwrap_or("false"), err, "approved", "boolean")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["order-id", "search-string", "sort-field", "ids", "max-results", "page-token", "site-id", "sort-order", "approved"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _orders_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.orders().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("project-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _orders_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.orders().list(opt.value_of("profile-id").unwrap_or(""), opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "site-id" => { + call = call.add_site_id(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "sort-field", "ids", "max-results", "page-token", "site-id", "sort-order"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placement_groups_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.placement_groups().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placement_groups_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::PlacementGroup::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_campaign_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.campaign_id_dimension_value.is_none() { + request.campaign_id_dimension_value = Some(Default::default()); + } + } + + fn request_create_info_init(request: &mut api::PlacementGroup) { + if request.create_info.is_none() { + request.create_info = Some(Default::default()); + } + } + + fn request_directory_site_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.directory_site_id_dimension_value.is_none() { + request.directory_site_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::PlacementGroup) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_pricing_schedule_init(request: &mut api::PlacementGroup) { + if request.pricing_schedule.is_none() { + request.pricing_schedule = Some(Default::default()); + } + } + + fn request_primary_placement_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.primary_placement_id_dimension_value.is_none() { + request.primary_placement_id_dimension_value = Some(Default::default()); + } + } + + fn request_programmatic_setting_init(request: &mut api::PlacementGroup) { + if request.programmatic_setting.is_none() { + request.programmatic_setting = Some(Default::default()); + } + } + + fn request_site_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.site_id_dimension_value.is_none() { + request.site_id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "comment" => { + request.comment = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id" => { + request.primary_placement_id = Some(value.unwrap_or("").to_string()); + }, + "campaign-id" => { + request.campaign_id = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.kind" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.value" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.dimension-name" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.etag" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.match-type" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id = Some(value.unwrap_or("").to_string()); + }, + "placement-group-type" => { + request_directory_site_id_dimension_value_init(&mut request); + request.placement_group_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "programmatic-setting.trafficker-emails" => { + request_programmatic_setting_init(&mut request); + if request.programmatic_setting.as_mut().unwrap().trafficker_emails.is_none() { + request.programmatic_setting.as_mut().unwrap().trafficker_emails = Some(Default::default()); + } + request.programmatic_setting.as_mut().unwrap().trafficker_emails.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "programmatic-setting.programmatic" => { + request_programmatic_setting_init(&mut request); + request.programmatic_setting.as_mut().unwrap().programmatic = Some(arg_from_str(value.unwrap_or("false"), err, "programmatic-setting.programmatic", "boolean")); + }, + "programmatic-setting.insertion-order-id" => { + request_programmatic_setting_init(&mut request); + request.programmatic_setting.as_mut().unwrap().insertion_order_id = Some(value.unwrap_or("").to_string()); + }, + "programmatic-setting.insertion-order-id-status" => { + request_programmatic_setting_init(&mut request); + request.programmatic_setting.as_mut().unwrap().insertion_order_id_status = Some(arg_from_str(value.unwrap_or("false"), err, "programmatic-setting.insertion-order-id-status", "boolean")); + }, + "programmatic-setting.adx-deal-ids" => { + request_programmatic_setting_init(&mut request); + if request.programmatic_setting.as_mut().unwrap().adx_deal_ids.is_none() { + request.programmatic_setting.as_mut().unwrap().adx_deal_ids = Some(Default::default()); + } + request.programmatic_setting.as_mut().unwrap().adx_deal_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "programmatic-setting.media-cost-nanos" => { + request_programmatic_setting_init(&mut request); + request.programmatic_setting.as_mut().unwrap().media_cost_nanos = Some(value.unwrap_or("").to_string()); + }, + "archived" => { + request_programmatic_setting_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "child-placement-ids" => { + request_programmatic_setting_init(&mut request); + if request.child_placement_ids.is_none() { + request.child_placement_ids = Some(Default::default()); + } + request.child_placement_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "content-category-id" => { + request_programmatic_setting_init(&mut request); + request.content_category_id = Some(value.unwrap_or("").to_string()); + }, + "external-id" => { + request_programmatic_setting_init(&mut request); + request.external_id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.kind" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.value" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.dimension-name" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.etag" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.match-type" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.id" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.value" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.dimension-name" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.etag" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.match-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.id" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "create-info.time" => { + request_create_info_init(&mut request); + request.create_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "site-id" => { + request_create_info_init(&mut request); + request.site_id = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.kind" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.value" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.dimension-name" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.etag" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.match-type" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.id" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "placement-strategy-id" => { + request_site_id_dimension_value_init(&mut request); + request.placement_strategy_id = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_site_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_site_id_dimension_value_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_site_id_dimension_value_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.start-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.end-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.flighted" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().flighted = Some(arg_from_str(value.unwrap_or("false"), err, "pricing-schedule.flighted", "boolean")); + }, + "pricing-schedule.disregard-overdelivery" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().disregard_overdelivery = Some(arg_from_str(value.unwrap_or("false"), err, "pricing-schedule.disregard-overdelivery", "boolean")); + }, + "pricing-schedule.pricing-type" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().pricing_type = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.cap-cost-option" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().cap_cost_option = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.testing-start-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().testing_start_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.floodlight-activity-id" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().floodlight_activity_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "adx-deal-ids", "archived", "campaign-id", "campaign-id-dimension-value", "cap-cost-option", "child-placement-ids", "comment", "content-category-id", "create-info", "dimension-name", "directory-site-id", "directory-site-id-dimension-value", "disregard-overdelivery", "end-date", "etag", "external-id", "flighted", "floodlight-activity-id", "id", "id-dimension-value", "insertion-order-id", "insertion-order-id-status", "kind", "last-modified-info", "match-type", "media-cost-nanos", "name", "placement-group-type", "placement-strategy-id", "pricing-schedule", "pricing-type", "primary-placement-id", "primary-placement-id-dimension-value", "programmatic", "programmatic-setting", "site-id", "site-id-dimension-value", "start-date", "subaccount-id", "testing-start-date", "time", "trafficker-emails", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.placement_groups().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placement_groups_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.placement_groups().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "site-ids" => { + call = call.add_site_ids(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "pricing-types" => { + call = call.add_pricing_types(value.unwrap_or("")); + }, + "placement-strategy-ids" => { + call = call.add_placement_strategy_ids(value.unwrap_or("")); + }, + "placement-group-type" => { + call = call.placement_group_type(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "directory-site-ids" => { + call = call.add_directory_site_ids(value.unwrap_or("")); + }, + "content-category-ids" => { + call = call.add_content_category_ids(value.unwrap_or("")); + }, + "campaign-ids" => { + call = call.add_campaign_ids(value.unwrap_or("")); + }, + "archived" => { + call = call.archived(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "advertiser-ids" => { + call = call.add_advertiser_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["placement-strategy-ids", "site-ids", "search-string", "content-category-ids", "directory-site-ids", "sort-field", "advertiser-ids", "archived", "ids", "max-results", "page-token", "sort-order", "placement-group-type", "pricing-types", "campaign-ids"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placement_groups_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::PlacementGroup::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_campaign_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.campaign_id_dimension_value.is_none() { + request.campaign_id_dimension_value = Some(Default::default()); + } + } + + fn request_create_info_init(request: &mut api::PlacementGroup) { + if request.create_info.is_none() { + request.create_info = Some(Default::default()); + } + } + + fn request_directory_site_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.directory_site_id_dimension_value.is_none() { + request.directory_site_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::PlacementGroup) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_pricing_schedule_init(request: &mut api::PlacementGroup) { + if request.pricing_schedule.is_none() { + request.pricing_schedule = Some(Default::default()); + } + } + + fn request_primary_placement_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.primary_placement_id_dimension_value.is_none() { + request.primary_placement_id_dimension_value = Some(Default::default()); + } + } + + fn request_programmatic_setting_init(request: &mut api::PlacementGroup) { + if request.programmatic_setting.is_none() { + request.programmatic_setting = Some(Default::default()); + } + } + + fn request_site_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.site_id_dimension_value.is_none() { + request.site_id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "comment" => { + request.comment = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id" => { + request.primary_placement_id = Some(value.unwrap_or("").to_string()); + }, + "campaign-id" => { + request.campaign_id = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.kind" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.value" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.dimension-name" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.etag" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.match-type" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id = Some(value.unwrap_or("").to_string()); + }, + "placement-group-type" => { + request_directory_site_id_dimension_value_init(&mut request); + request.placement_group_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "programmatic-setting.trafficker-emails" => { + request_programmatic_setting_init(&mut request); + if request.programmatic_setting.as_mut().unwrap().trafficker_emails.is_none() { + request.programmatic_setting.as_mut().unwrap().trafficker_emails = Some(Default::default()); + } + request.programmatic_setting.as_mut().unwrap().trafficker_emails.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "programmatic-setting.programmatic" => { + request_programmatic_setting_init(&mut request); + request.programmatic_setting.as_mut().unwrap().programmatic = Some(arg_from_str(value.unwrap_or("false"), err, "programmatic-setting.programmatic", "boolean")); + }, + "programmatic-setting.insertion-order-id" => { + request_programmatic_setting_init(&mut request); + request.programmatic_setting.as_mut().unwrap().insertion_order_id = Some(value.unwrap_or("").to_string()); + }, + "programmatic-setting.insertion-order-id-status" => { + request_programmatic_setting_init(&mut request); + request.programmatic_setting.as_mut().unwrap().insertion_order_id_status = Some(arg_from_str(value.unwrap_or("false"), err, "programmatic-setting.insertion-order-id-status", "boolean")); + }, + "programmatic-setting.adx-deal-ids" => { + request_programmatic_setting_init(&mut request); + if request.programmatic_setting.as_mut().unwrap().adx_deal_ids.is_none() { + request.programmatic_setting.as_mut().unwrap().adx_deal_ids = Some(Default::default()); + } + request.programmatic_setting.as_mut().unwrap().adx_deal_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "programmatic-setting.media-cost-nanos" => { + request_programmatic_setting_init(&mut request); + request.programmatic_setting.as_mut().unwrap().media_cost_nanos = Some(value.unwrap_or("").to_string()); + }, + "archived" => { + request_programmatic_setting_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "child-placement-ids" => { + request_programmatic_setting_init(&mut request); + if request.child_placement_ids.is_none() { + request.child_placement_ids = Some(Default::default()); + } + request.child_placement_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "content-category-id" => { + request_programmatic_setting_init(&mut request); + request.content_category_id = Some(value.unwrap_or("").to_string()); + }, + "external-id" => { + request_programmatic_setting_init(&mut request); + request.external_id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.kind" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.value" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.dimension-name" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.etag" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.match-type" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.id" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.value" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.dimension-name" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.etag" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.match-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.id" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "create-info.time" => { + request_create_info_init(&mut request); + request.create_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "site-id" => { + request_create_info_init(&mut request); + request.site_id = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.kind" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.value" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.dimension-name" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.etag" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.match-type" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.id" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "placement-strategy-id" => { + request_site_id_dimension_value_init(&mut request); + request.placement_strategy_id = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_site_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_site_id_dimension_value_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_site_id_dimension_value_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.start-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.end-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.flighted" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().flighted = Some(arg_from_str(value.unwrap_or("false"), err, "pricing-schedule.flighted", "boolean")); + }, + "pricing-schedule.disregard-overdelivery" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().disregard_overdelivery = Some(arg_from_str(value.unwrap_or("false"), err, "pricing-schedule.disregard-overdelivery", "boolean")); + }, + "pricing-schedule.pricing-type" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().pricing_type = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.cap-cost-option" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().cap_cost_option = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.testing-start-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().testing_start_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.floodlight-activity-id" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().floodlight_activity_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "adx-deal-ids", "archived", "campaign-id", "campaign-id-dimension-value", "cap-cost-option", "child-placement-ids", "comment", "content-category-id", "create-info", "dimension-name", "directory-site-id", "directory-site-id-dimension-value", "disregard-overdelivery", "end-date", "etag", "external-id", "flighted", "floodlight-activity-id", "id", "id-dimension-value", "insertion-order-id", "insertion-order-id-status", "kind", "last-modified-info", "match-type", "media-cost-nanos", "name", "placement-group-type", "placement-strategy-id", "pricing-schedule", "pricing-type", "primary-placement-id", "primary-placement-id-dimension-value", "programmatic", "programmatic-setting", "site-id", "site-id-dimension-value", "start-date", "subaccount-id", "testing-start-date", "time", "trafficker-emails", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.placement_groups().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placement_groups_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::PlacementGroup::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_campaign_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.campaign_id_dimension_value.is_none() { + request.campaign_id_dimension_value = Some(Default::default()); + } + } + + fn request_create_info_init(request: &mut api::PlacementGroup) { + if request.create_info.is_none() { + request.create_info = Some(Default::default()); + } + } + + fn request_directory_site_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.directory_site_id_dimension_value.is_none() { + request.directory_site_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::PlacementGroup) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_pricing_schedule_init(request: &mut api::PlacementGroup) { + if request.pricing_schedule.is_none() { + request.pricing_schedule = Some(Default::default()); + } + } + + fn request_primary_placement_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.primary_placement_id_dimension_value.is_none() { + request.primary_placement_id_dimension_value = Some(Default::default()); + } + } + + fn request_programmatic_setting_init(request: &mut api::PlacementGroup) { + if request.programmatic_setting.is_none() { + request.programmatic_setting = Some(Default::default()); + } + } + + fn request_site_id_dimension_value_init(request: &mut api::PlacementGroup) { + if request.site_id_dimension_value.is_none() { + request.site_id_dimension_value = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "comment" => { + request.comment = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id" => { + request.primary_placement_id = Some(value.unwrap_or("").to_string()); + }, + "campaign-id" => { + request.campaign_id = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.kind" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.value" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.dimension-name" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.etag" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.match-type" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id = Some(value.unwrap_or("").to_string()); + }, + "placement-group-type" => { + request_directory_site_id_dimension_value_init(&mut request); + request.placement_group_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "programmatic-setting.trafficker-emails" => { + request_programmatic_setting_init(&mut request); + if request.programmatic_setting.as_mut().unwrap().trafficker_emails.is_none() { + request.programmatic_setting.as_mut().unwrap().trafficker_emails = Some(Default::default()); + } + request.programmatic_setting.as_mut().unwrap().trafficker_emails.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "programmatic-setting.programmatic" => { + request_programmatic_setting_init(&mut request); + request.programmatic_setting.as_mut().unwrap().programmatic = Some(arg_from_str(value.unwrap_or("false"), err, "programmatic-setting.programmatic", "boolean")); + }, + "programmatic-setting.insertion-order-id" => { + request_programmatic_setting_init(&mut request); + request.programmatic_setting.as_mut().unwrap().insertion_order_id = Some(value.unwrap_or("").to_string()); + }, + "programmatic-setting.insertion-order-id-status" => { + request_programmatic_setting_init(&mut request); + request.programmatic_setting.as_mut().unwrap().insertion_order_id_status = Some(arg_from_str(value.unwrap_or("false"), err, "programmatic-setting.insertion-order-id-status", "boolean")); + }, + "programmatic-setting.adx-deal-ids" => { + request_programmatic_setting_init(&mut request); + if request.programmatic_setting.as_mut().unwrap().adx_deal_ids.is_none() { + request.programmatic_setting.as_mut().unwrap().adx_deal_ids = Some(Default::default()); + } + request.programmatic_setting.as_mut().unwrap().adx_deal_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "programmatic-setting.media-cost-nanos" => { + request_programmatic_setting_init(&mut request); + request.programmatic_setting.as_mut().unwrap().media_cost_nanos = Some(value.unwrap_or("").to_string()); + }, + "archived" => { + request_programmatic_setting_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "child-placement-ids" => { + request_programmatic_setting_init(&mut request); + if request.child_placement_ids.is_none() { + request.child_placement_ids = Some(Default::default()); + } + request.child_placement_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "content-category-id" => { + request_programmatic_setting_init(&mut request); + request.content_category_id = Some(value.unwrap_or("").to_string()); + }, + "external-id" => { + request_programmatic_setting_init(&mut request); + request.external_id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.kind" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.value" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.dimension-name" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.etag" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.match-type" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "primary-placement-id-dimension-value.id" => { + request_primary_placement_id_dimension_value_init(&mut request); + request.primary_placement_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.value" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.dimension-name" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.etag" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.match-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.id" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "create-info.time" => { + request_create_info_init(&mut request); + request.create_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "site-id" => { + request_create_info_init(&mut request); + request.site_id = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.kind" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.value" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.dimension-name" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.etag" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.match-type" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.id" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "placement-strategy-id" => { + request_site_id_dimension_value_init(&mut request); + request.placement_strategy_id = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_site_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_site_id_dimension_value_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_site_id_dimension_value_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.start-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.end-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.flighted" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().flighted = Some(arg_from_str(value.unwrap_or("false"), err, "pricing-schedule.flighted", "boolean")); + }, + "pricing-schedule.disregard-overdelivery" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().disregard_overdelivery = Some(arg_from_str(value.unwrap_or("false"), err, "pricing-schedule.disregard-overdelivery", "boolean")); + }, + "pricing-schedule.pricing-type" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().pricing_type = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.cap-cost-option" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().cap_cost_option = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.testing-start-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().testing_start_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.floodlight-activity-id" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().floodlight_activity_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "advertiser-id", "advertiser-id-dimension-value", "adx-deal-ids", "archived", "campaign-id", "campaign-id-dimension-value", "cap-cost-option", "child-placement-ids", "comment", "content-category-id", "create-info", "dimension-name", "directory-site-id", "directory-site-id-dimension-value", "disregard-overdelivery", "end-date", "etag", "external-id", "flighted", "floodlight-activity-id", "id", "id-dimension-value", "insertion-order-id", "insertion-order-id-status", "kind", "last-modified-info", "match-type", "media-cost-nanos", "name", "placement-group-type", "placement-strategy-id", "pricing-schedule", "pricing-type", "primary-placement-id", "primary-placement-id-dimension-value", "programmatic", "programmatic-setting", "site-id", "site-id-dimension-value", "start-date", "subaccount-id", "testing-start-date", "time", "trafficker-emails", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.placement_groups().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placement_strategies_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.placement_strategies().delete(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _placement_strategies_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.placement_strategies().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placement_strategies_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::PlacementStrategy::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.placement_strategies().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placement_strategies_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.placement_strategies().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "sort-field", "ids", "max-results", "page-token", "sort-order"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placement_strategies_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::PlacementStrategy::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.placement_strategies().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placement_strategies_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::PlacementStrategy::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.placement_strategies().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placements_generatetags(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.placements().generatetags(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "tag-formats" => { + call = call.add_tag_formats(value.unwrap_or("")); + }, + "placement-ids" => { + call = call.add_placement_ids(value.unwrap_or("")); + }, + "campaign-id" => { + call = call.campaign_id(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["tag-formats", "placement-ids", "campaign-id"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placements_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.placements().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placements_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Placement::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::Placement) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_campaign_id_dimension_value_init(request: &mut api::Placement) { + if request.campaign_id_dimension_value.is_none() { + request.campaign_id_dimension_value = Some(Default::default()); + } + } + + fn request_create_info_init(request: &mut api::Placement) { + if request.create_info.is_none() { + request.create_info = Some(Default::default()); + } + } + + fn request_directory_site_id_dimension_value_init(request: &mut api::Placement) { + if request.directory_site_id_dimension_value.is_none() { + request.directory_site_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Placement) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::Placement) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_lookback_configuration_init(request: &mut api::Placement) { + if request.lookback_configuration.is_none() { + request.lookback_configuration = Some(Default::default()); + } + } + + fn request_placement_group_id_dimension_value_init(request: &mut api::Placement) { + if request.placement_group_id_dimension_value.is_none() { + request.placement_group_id_dimension_value = Some(Default::default()); + } + } + + fn request_pricing_schedule_init(request: &mut api::Placement) { + if request.pricing_schedule.is_none() { + request.pricing_schedule = Some(Default::default()); + } + } + + fn request_publisher_update_info_init(request: &mut api::Placement) { + if request.publisher_update_info.is_none() { + request.publisher_update_info = Some(Default::default()); + } + } + + fn request_site_id_dimension_value_init(request: &mut api::Placement) { + if request.site_id_dimension_value.is_none() { + request.site_id_dimension_value = Some(Default::default()); + } + } + + fn request_size_init(request: &mut api::Placement) { + if request.size.is_none() { + request.size = Some(Default::default()); + } + } + + fn request_tag_setting_init(request: &mut api::Placement) { + if request.tag_setting.is_none() { + request.tag_setting = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "comment" => { + request.comment = Some(value.unwrap_or("").to_string()); + }, + "campaign-id" => { + request.campaign_id = Some(value.unwrap_or("").to_string()); + }, + "payment-source" => { + request.payment_source = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.kind" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.value" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.dimension-name" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.etag" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.match-type" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "key-name" => { + request_directory_site_id_dimension_value_init(&mut request); + request.key_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "archived" => { + request_advertiser_id_dimension_value_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "publisher-update-info.time" => { + request_publisher_update_info_init(&mut request); + request.publisher_update_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "tag-formats" => { + request_publisher_update_info_init(&mut request); + if request.tag_formats.is_none() { + request.tag_formats = Some(Default::default()); + } + request.tag_formats.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "payment-approved" => { + request_publisher_update_info_init(&mut request); + request.payment_approved = Some(arg_from_str(value.unwrap_or("false"), err, "payment-approved", "boolean")); + }, + "tag-setting.include-click-through-urls" => { + request_tag_setting_init(&mut request); + request.tag_setting.as_mut().unwrap().include_click_through_urls = Some(arg_from_str(value.unwrap_or("false"), err, "tag-setting.include-click-through-urls", "boolean")); + }, + "tag-setting.include-click-tracking" => { + request_tag_setting_init(&mut request); + request.tag_setting.as_mut().unwrap().include_click_tracking = Some(arg_from_str(value.unwrap_or("false"), err, "tag-setting.include-click-tracking", "boolean")); + }, + "tag-setting.additional-key-values" => { + request_tag_setting_init(&mut request); + request.tag_setting.as_mut().unwrap().additional_key_values = Some(value.unwrap_or("").to_string()); + }, + "tag-setting.keyword-option" => { + request_tag_setting_init(&mut request); + request.tag_setting.as_mut().unwrap().keyword_option = Some(value.unwrap_or("").to_string()); + }, + "content-category-id" => { + request_tag_setting_init(&mut request); + request.content_category_id = Some(value.unwrap_or("").to_string()); + }, + "external-id" => { + request_tag_setting_init(&mut request); + request.external_id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.width" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().width = Some(arg_from_str(value.unwrap_or("-0"), err, "size.width", "integer")); + }, + "size.kind" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "size.iab" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().iab = Some(arg_from_str(value.unwrap_or("false"), err, "size.iab", "boolean")); + }, + "size.id" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.height" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().height = Some(arg_from_str(value.unwrap_or("-0"), err, "size.height", "integer")); + }, + "ssl-required" => { + request_size_init(&mut request); + request.ssl_required = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-required", "boolean")); + }, + "status" => { + request_size_init(&mut request); + request.status = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.value" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.dimension-name" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.etag" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.match-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.id" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "primary" => { + request_campaign_id_dimension_value_init(&mut request); + request.primary = Some(arg_from_str(value.unwrap_or("false"), err, "primary", "boolean")); + }, + "placement-group-id" => { + request_campaign_id_dimension_value_init(&mut request); + request.placement_group_id = Some(value.unwrap_or("").to_string()); + }, + "create-info.time" => { + request_create_info_init(&mut request); + request.create_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "site-id" => { + request_create_info_init(&mut request); + request.site_id = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.kind" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.value" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.dimension-name" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.etag" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.match-type" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.id" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "compatibility" => { + request_site_id_dimension_value_init(&mut request); + request.compatibility = Some(value.unwrap_or("").to_string()); + }, + "placement-strategy-id" => { + request_site_id_dimension_value_init(&mut request); + request.placement_strategy_id = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.kind" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.value" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.dimension-name" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.etag" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.match-type" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.id" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_placement_group_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_placement_group_id_dimension_value_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_placement_group_id_dimension_value_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "lookback-configuration.click-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().click_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.click-duration", "integer")); + }, + "lookback-configuration.post-impression-activities-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().post_impression_activities_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.post-impression-activities-duration", "integer")); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.start-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.end-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.flighted" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().flighted = Some(arg_from_str(value.unwrap_or("false"), err, "pricing-schedule.flighted", "boolean")); + }, + "pricing-schedule.disregard-overdelivery" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().disregard_overdelivery = Some(arg_from_str(value.unwrap_or("false"), err, "pricing-schedule.disregard-overdelivery", "boolean")); + }, + "pricing-schedule.pricing-type" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().pricing_type = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.cap-cost-option" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().cap_cost_option = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.testing-start-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().testing_start_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.floodlight-activity-id" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().floodlight_activity_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "additional-key-values", "advertiser-id", "advertiser-id-dimension-value", "archived", "campaign-id", "campaign-id-dimension-value", "cap-cost-option", "click-duration", "comment", "compatibility", "content-category-id", "create-info", "dimension-name", "directory-site-id", "directory-site-id-dimension-value", "disregard-overdelivery", "end-date", "etag", "external-id", "flighted", "floodlight-activity-id", "height", "iab", "id", "id-dimension-value", "include-click-through-urls", "include-click-tracking", "key-name", "keyword-option", "kind", "last-modified-info", "lookback-configuration", "match-type", "name", "payment-approved", "payment-source", "placement-group-id", "placement-group-id-dimension-value", "placement-strategy-id", "post-impression-activities-duration", "pricing-schedule", "pricing-type", "primary", "publisher-update-info", "site-id", "site-id-dimension-value", "size", "ssl-required", "start-date", "status", "subaccount-id", "tag-formats", "tag-setting", "testing-start-date", "time", "value", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.placements().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placements_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.placements().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "size-ids" => { + call = call.add_size_ids(value.unwrap_or("")); + }, + "site-ids" => { + call = call.add_site_ids(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "pricing-types" => { + call = call.add_pricing_types(value.unwrap_or("")); + }, + "placement-strategy-ids" => { + call = call.add_placement_strategy_ids(value.unwrap_or("")); + }, + "payment-source" => { + call = call.payment_source(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "group-ids" => { + call = call.add_group_ids(value.unwrap_or("")); + }, + "directory-site-ids" => { + call = call.add_directory_site_ids(value.unwrap_or("")); + }, + "content-category-ids" => { + call = call.add_content_category_ids(value.unwrap_or("")); + }, + "compatibilities" => { + call = call.add_compatibilities(value.unwrap_or("")); + }, + "campaign-ids" => { + call = call.add_campaign_ids(value.unwrap_or("")); + }, + "archived" => { + call = call.archived(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "advertiser-ids" => { + call = call.add_advertiser_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["placement-strategy-ids", "site-ids", "search-string", "content-category-ids", "directory-site-ids", "sort-field", "advertiser-ids", "archived", "payment-source", "ids", "max-results", "size-ids", "page-token", "compatibilities", "sort-order", "pricing-types", "campaign-ids", "group-ids"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placements_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Placement::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::Placement) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_campaign_id_dimension_value_init(request: &mut api::Placement) { + if request.campaign_id_dimension_value.is_none() { + request.campaign_id_dimension_value = Some(Default::default()); + } + } + + fn request_create_info_init(request: &mut api::Placement) { + if request.create_info.is_none() { + request.create_info = Some(Default::default()); + } + } + + fn request_directory_site_id_dimension_value_init(request: &mut api::Placement) { + if request.directory_site_id_dimension_value.is_none() { + request.directory_site_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Placement) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::Placement) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_lookback_configuration_init(request: &mut api::Placement) { + if request.lookback_configuration.is_none() { + request.lookback_configuration = Some(Default::default()); + } + } + + fn request_placement_group_id_dimension_value_init(request: &mut api::Placement) { + if request.placement_group_id_dimension_value.is_none() { + request.placement_group_id_dimension_value = Some(Default::default()); + } + } + + fn request_pricing_schedule_init(request: &mut api::Placement) { + if request.pricing_schedule.is_none() { + request.pricing_schedule = Some(Default::default()); + } + } + + fn request_publisher_update_info_init(request: &mut api::Placement) { + if request.publisher_update_info.is_none() { + request.publisher_update_info = Some(Default::default()); + } + } + + fn request_site_id_dimension_value_init(request: &mut api::Placement) { + if request.site_id_dimension_value.is_none() { + request.site_id_dimension_value = Some(Default::default()); + } + } + + fn request_size_init(request: &mut api::Placement) { + if request.size.is_none() { + request.size = Some(Default::default()); + } + } + + fn request_tag_setting_init(request: &mut api::Placement) { + if request.tag_setting.is_none() { + request.tag_setting = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "comment" => { + request.comment = Some(value.unwrap_or("").to_string()); + }, + "campaign-id" => { + request.campaign_id = Some(value.unwrap_or("").to_string()); + }, + "payment-source" => { + request.payment_source = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.kind" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.value" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.dimension-name" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.etag" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.match-type" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "key-name" => { + request_directory_site_id_dimension_value_init(&mut request); + request.key_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "archived" => { + request_advertiser_id_dimension_value_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "publisher-update-info.time" => { + request_publisher_update_info_init(&mut request); + request.publisher_update_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "tag-formats" => { + request_publisher_update_info_init(&mut request); + if request.tag_formats.is_none() { + request.tag_formats = Some(Default::default()); + } + request.tag_formats.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "payment-approved" => { + request_publisher_update_info_init(&mut request); + request.payment_approved = Some(arg_from_str(value.unwrap_or("false"), err, "payment-approved", "boolean")); + }, + "tag-setting.include-click-through-urls" => { + request_tag_setting_init(&mut request); + request.tag_setting.as_mut().unwrap().include_click_through_urls = Some(arg_from_str(value.unwrap_or("false"), err, "tag-setting.include-click-through-urls", "boolean")); + }, + "tag-setting.include-click-tracking" => { + request_tag_setting_init(&mut request); + request.tag_setting.as_mut().unwrap().include_click_tracking = Some(arg_from_str(value.unwrap_or("false"), err, "tag-setting.include-click-tracking", "boolean")); + }, + "tag-setting.additional-key-values" => { + request_tag_setting_init(&mut request); + request.tag_setting.as_mut().unwrap().additional_key_values = Some(value.unwrap_or("").to_string()); + }, + "tag-setting.keyword-option" => { + request_tag_setting_init(&mut request); + request.tag_setting.as_mut().unwrap().keyword_option = Some(value.unwrap_or("").to_string()); + }, + "content-category-id" => { + request_tag_setting_init(&mut request); + request.content_category_id = Some(value.unwrap_or("").to_string()); + }, + "external-id" => { + request_tag_setting_init(&mut request); + request.external_id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.width" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().width = Some(arg_from_str(value.unwrap_or("-0"), err, "size.width", "integer")); + }, + "size.kind" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "size.iab" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().iab = Some(arg_from_str(value.unwrap_or("false"), err, "size.iab", "boolean")); + }, + "size.id" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.height" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().height = Some(arg_from_str(value.unwrap_or("-0"), err, "size.height", "integer")); + }, + "ssl-required" => { + request_size_init(&mut request); + request.ssl_required = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-required", "boolean")); + }, + "status" => { + request_size_init(&mut request); + request.status = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.value" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.dimension-name" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.etag" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.match-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.id" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "primary" => { + request_campaign_id_dimension_value_init(&mut request); + request.primary = Some(arg_from_str(value.unwrap_or("false"), err, "primary", "boolean")); + }, + "placement-group-id" => { + request_campaign_id_dimension_value_init(&mut request); + request.placement_group_id = Some(value.unwrap_or("").to_string()); + }, + "create-info.time" => { + request_create_info_init(&mut request); + request.create_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "site-id" => { + request_create_info_init(&mut request); + request.site_id = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.kind" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.value" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.dimension-name" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.etag" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.match-type" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.id" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "compatibility" => { + request_site_id_dimension_value_init(&mut request); + request.compatibility = Some(value.unwrap_or("").to_string()); + }, + "placement-strategy-id" => { + request_site_id_dimension_value_init(&mut request); + request.placement_strategy_id = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.kind" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.value" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.dimension-name" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.etag" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.match-type" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.id" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_placement_group_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_placement_group_id_dimension_value_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_placement_group_id_dimension_value_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "lookback-configuration.click-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().click_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.click-duration", "integer")); + }, + "lookback-configuration.post-impression-activities-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().post_impression_activities_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.post-impression-activities-duration", "integer")); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.start-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.end-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.flighted" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().flighted = Some(arg_from_str(value.unwrap_or("false"), err, "pricing-schedule.flighted", "boolean")); + }, + "pricing-schedule.disregard-overdelivery" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().disregard_overdelivery = Some(arg_from_str(value.unwrap_or("false"), err, "pricing-schedule.disregard-overdelivery", "boolean")); + }, + "pricing-schedule.pricing-type" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().pricing_type = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.cap-cost-option" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().cap_cost_option = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.testing-start-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().testing_start_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.floodlight-activity-id" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().floodlight_activity_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "additional-key-values", "advertiser-id", "advertiser-id-dimension-value", "archived", "campaign-id", "campaign-id-dimension-value", "cap-cost-option", "click-duration", "comment", "compatibility", "content-category-id", "create-info", "dimension-name", "directory-site-id", "directory-site-id-dimension-value", "disregard-overdelivery", "end-date", "etag", "external-id", "flighted", "floodlight-activity-id", "height", "iab", "id", "id-dimension-value", "include-click-through-urls", "include-click-tracking", "key-name", "keyword-option", "kind", "last-modified-info", "lookback-configuration", "match-type", "name", "payment-approved", "payment-source", "placement-group-id", "placement-group-id-dimension-value", "placement-strategy-id", "post-impression-activities-duration", "pricing-schedule", "pricing-type", "primary", "publisher-update-info", "site-id", "site-id-dimension-value", "size", "ssl-required", "start-date", "status", "subaccount-id", "tag-formats", "tag-setting", "testing-start-date", "time", "value", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.placements().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _placements_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Placement::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::Placement) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_campaign_id_dimension_value_init(request: &mut api::Placement) { + if request.campaign_id_dimension_value.is_none() { + request.campaign_id_dimension_value = Some(Default::default()); + } + } + + fn request_create_info_init(request: &mut api::Placement) { + if request.create_info.is_none() { + request.create_info = Some(Default::default()); + } + } + + fn request_directory_site_id_dimension_value_init(request: &mut api::Placement) { + if request.directory_site_id_dimension_value.is_none() { + request.directory_site_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Placement) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_last_modified_info_init(request: &mut api::Placement) { + if request.last_modified_info.is_none() { + request.last_modified_info = Some(Default::default()); + } + } + + fn request_lookback_configuration_init(request: &mut api::Placement) { + if request.lookback_configuration.is_none() { + request.lookback_configuration = Some(Default::default()); + } + } + + fn request_placement_group_id_dimension_value_init(request: &mut api::Placement) { + if request.placement_group_id_dimension_value.is_none() { + request.placement_group_id_dimension_value = Some(Default::default()); + } + } + + fn request_pricing_schedule_init(request: &mut api::Placement) { + if request.pricing_schedule.is_none() { + request.pricing_schedule = Some(Default::default()); + } + } + + fn request_publisher_update_info_init(request: &mut api::Placement) { + if request.publisher_update_info.is_none() { + request.publisher_update_info = Some(Default::default()); + } + } + + fn request_site_id_dimension_value_init(request: &mut api::Placement) { + if request.site_id_dimension_value.is_none() { + request.site_id_dimension_value = Some(Default::default()); + } + } + + fn request_size_init(request: &mut api::Placement) { + if request.size.is_none() { + request.size = Some(Default::default()); + } + } + + fn request_tag_setting_init(request: &mut api::Placement) { + if request.tag_setting.is_none() { + request.tag_setting = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "comment" => { + request.comment = Some(value.unwrap_or("").to_string()); + }, + "campaign-id" => { + request.campaign_id = Some(value.unwrap_or("").to_string()); + }, + "payment-source" => { + request.payment_source = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.kind" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.value" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.dimension-name" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.etag" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.match-type" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "key-name" => { + request_directory_site_id_dimension_value_init(&mut request); + request.key_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "archived" => { + request_advertiser_id_dimension_value_init(&mut request); + request.archived = Some(arg_from_str(value.unwrap_or("false"), err, "archived", "boolean")); + }, + "publisher-update-info.time" => { + request_publisher_update_info_init(&mut request); + request.publisher_update_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "tag-formats" => { + request_publisher_update_info_init(&mut request); + if request.tag_formats.is_none() { + request.tag_formats = Some(Default::default()); + } + request.tag_formats.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "payment-approved" => { + request_publisher_update_info_init(&mut request); + request.payment_approved = Some(arg_from_str(value.unwrap_or("false"), err, "payment-approved", "boolean")); + }, + "tag-setting.include-click-through-urls" => { + request_tag_setting_init(&mut request); + request.tag_setting.as_mut().unwrap().include_click_through_urls = Some(arg_from_str(value.unwrap_or("false"), err, "tag-setting.include-click-through-urls", "boolean")); + }, + "tag-setting.include-click-tracking" => { + request_tag_setting_init(&mut request); + request.tag_setting.as_mut().unwrap().include_click_tracking = Some(arg_from_str(value.unwrap_or("false"), err, "tag-setting.include-click-tracking", "boolean")); + }, + "tag-setting.additional-key-values" => { + request_tag_setting_init(&mut request); + request.tag_setting.as_mut().unwrap().additional_key_values = Some(value.unwrap_or("").to_string()); + }, + "tag-setting.keyword-option" => { + request_tag_setting_init(&mut request); + request.tag_setting.as_mut().unwrap().keyword_option = Some(value.unwrap_or("").to_string()); + }, + "content-category-id" => { + request_tag_setting_init(&mut request); + request.content_category_id = Some(value.unwrap_or("").to_string()); + }, + "external-id" => { + request_tag_setting_init(&mut request); + request.external_id = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.width" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().width = Some(arg_from_str(value.unwrap_or("-0"), err, "size.width", "integer")); + }, + "size.kind" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "size.iab" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().iab = Some(arg_from_str(value.unwrap_or("false"), err, "size.iab", "boolean")); + }, + "size.id" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "size.height" => { + request_size_init(&mut request); + request.size.as_mut().unwrap().height = Some(arg_from_str(value.unwrap_or("-0"), err, "size.height", "integer")); + }, + "ssl-required" => { + request_size_init(&mut request); + request.ssl_required = Some(arg_from_str(value.unwrap_or("false"), err, "ssl-required", "boolean")); + }, + "status" => { + request_size_init(&mut request); + request.status = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.kind" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.value" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.dimension-name" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.etag" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.match-type" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "campaign-id-dimension-value.id" => { + request_campaign_id_dimension_value_init(&mut request); + request.campaign_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "primary" => { + request_campaign_id_dimension_value_init(&mut request); + request.primary = Some(arg_from_str(value.unwrap_or("false"), err, "primary", "boolean")); + }, + "placement-group-id" => { + request_campaign_id_dimension_value_init(&mut request); + request.placement_group_id = Some(value.unwrap_or("").to_string()); + }, + "create-info.time" => { + request_create_info_init(&mut request); + request.create_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "site-id" => { + request_create_info_init(&mut request); + request.site_id = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.kind" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.value" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.dimension-name" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.etag" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.match-type" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "site-id-dimension-value.id" => { + request_site_id_dimension_value_init(&mut request); + request.site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "compatibility" => { + request_site_id_dimension_value_init(&mut request); + request.compatibility = Some(value.unwrap_or("").to_string()); + }, + "placement-strategy-id" => { + request_site_id_dimension_value_init(&mut request); + request.placement_strategy_id = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.kind" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.value" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.dimension-name" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.etag" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.match-type" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "placement-group-id-dimension-value.id" => { + request_placement_group_id_dimension_value_init(&mut request); + request.placement_group_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_placement_group_id_dimension_value_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_placement_group_id_dimension_value_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_placement_group_id_dimension_value_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "lookback-configuration.click-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().click_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.click-duration", "integer")); + }, + "lookback-configuration.post-impression-activities-duration" => { + request_lookback_configuration_init(&mut request); + request.lookback_configuration.as_mut().unwrap().post_impression_activities_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "lookback-configuration.post-impression-activities-duration", "integer")); + }, + "last-modified-info.time" => { + request_last_modified_info_init(&mut request); + request.last_modified_info.as_mut().unwrap().time = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.start-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.end-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.flighted" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().flighted = Some(arg_from_str(value.unwrap_or("false"), err, "pricing-schedule.flighted", "boolean")); + }, + "pricing-schedule.disregard-overdelivery" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().disregard_overdelivery = Some(arg_from_str(value.unwrap_or("false"), err, "pricing-schedule.disregard-overdelivery", "boolean")); + }, + "pricing-schedule.pricing-type" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().pricing_type = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.cap-cost-option" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().cap_cost_option = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.testing-start-date" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().testing_start_date = Some(value.unwrap_or("").to_string()); + }, + "pricing-schedule.floodlight-activity-id" => { + request_pricing_schedule_init(&mut request); + request.pricing_schedule.as_mut().unwrap().floodlight_activity_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "additional-key-values", "advertiser-id", "advertiser-id-dimension-value", "archived", "campaign-id", "campaign-id-dimension-value", "cap-cost-option", "click-duration", "comment", "compatibility", "content-category-id", "create-info", "dimension-name", "directory-site-id", "directory-site-id-dimension-value", "disregard-overdelivery", "end-date", "etag", "external-id", "flighted", "floodlight-activity-id", "height", "iab", "id", "id-dimension-value", "include-click-through-urls", "include-click-tracking", "key-name", "keyword-option", "kind", "last-modified-info", "lookback-configuration", "match-type", "name", "payment-approved", "payment-source", "placement-group-id", "placement-group-id-dimension-value", "placement-strategy-id", "post-impression-activities-duration", "pricing-schedule", "pricing-type", "primary", "publisher-update-info", "site-id", "site-id-dimension-value", "size", "ssl-required", "start-date", "status", "subaccount-id", "tag-formats", "tag-setting", "testing-start-date", "time", "value", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.placements().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _platform_types_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.platform_types().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _platform_types_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.platform_types().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _postal_codes_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.postal_codes().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("code").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _postal_codes_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.postal_codes().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _projects_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _projects_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "advertiser-ids" => { + call = call.add_advertiser_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "sort-field", "advertiser-ids", "ids", "max-results", "page-token", "sort-order"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _regions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.regions().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _remarketing_list_shares_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.remarketing_list_shares().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("remarketing-list-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _remarketing_list_shares_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::RemarketingListShare::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "shared-advertiser-ids" => { + if request.shared_advertiser_ids.is_none() { + request.shared_advertiser_ids = Some(Default::default()); + } + request.shared_advertiser_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "remarketing-list-id" => { + request.remarketing_list_id = Some(value.unwrap_or("").to_string()); + }, + "shared-account-ids" => { + if request.shared_account_ids.is_none() { + request.shared_account_ids = Some(Default::default()); + } + request.shared_account_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind", "remarketing-list-id", "shared-account-ids", "shared-advertiser-ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.remarketing_list_shares().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("remarketing-list-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _remarketing_list_shares_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::RemarketingListShare::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "shared-advertiser-ids" => { + if request.shared_advertiser_ids.is_none() { + request.shared_advertiser_ids = Some(Default::default()); + } + request.shared_advertiser_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "remarketing-list-id" => { + request.remarketing_list_id = Some(value.unwrap_or("").to_string()); + }, + "shared-account-ids" => { + if request.shared_account_ids.is_none() { + request.shared_account_ids = Some(Default::default()); + } + request.shared_account_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind", "remarketing-list-id", "shared-account-ids", "shared-advertiser-ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.remarketing_list_shares().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _remarketing_lists_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.remarketing_lists().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _remarketing_lists_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::RemarketingList::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::RemarketingList) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_list_population_rule_init(request: &mut api::RemarketingList) { + if request.list_population_rule.is_none() { + request.list_population_rule = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "list-population-rule.floodlight-activity-name" => { + request_list_population_rule_init(&mut request); + request.list_population_rule.as_mut().unwrap().floodlight_activity_name = Some(value.unwrap_or("").to_string()); + }, + "list-population-rule.floodlight-activity-id" => { + request_list_population_rule_init(&mut request); + request.list_population_rule.as_mut().unwrap().floodlight_activity_id = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_list_population_rule_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_list_population_rule_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "description" => { + request_list_population_rule_init(&mut request); + request.description = Some(value.unwrap_or("").to_string()); + }, + "list-size" => { + request_list_population_rule_init(&mut request); + request.list_size = Some(value.unwrap_or("").to_string()); + }, + "life-span" => { + request_list_population_rule_init(&mut request); + request.life_span = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_list_population_rule_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request_list_population_rule_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_list_population_rule_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "list-source" => { + request_advertiser_id_dimension_value_init(&mut request); + request.list_source = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "advertiser-id", "advertiser-id-dimension-value", "description", "dimension-name", "etag", "floodlight-activity-id", "floodlight-activity-name", "id", "kind", "life-span", "list-population-rule", "list-size", "list-source", "match-type", "name", "subaccount-id", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.remarketing_lists().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _remarketing_lists_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.remarketing_lists().list(opt.value_of("profile-id").unwrap_or(""), opt.value_of("advertiser-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "name" => { + call = call.name(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "floodlight-activity-id" => { + call = call.floodlight_activity_id(value.unwrap_or("")); + }, + "active" => { + call = call.active(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["name", "sort-field", "max-results", "page-token", "sort-order", "active", "floodlight-activity-id"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _remarketing_lists_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::RemarketingList::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::RemarketingList) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_list_population_rule_init(request: &mut api::RemarketingList) { + if request.list_population_rule.is_none() { + request.list_population_rule = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "list-population-rule.floodlight-activity-name" => { + request_list_population_rule_init(&mut request); + request.list_population_rule.as_mut().unwrap().floodlight_activity_name = Some(value.unwrap_or("").to_string()); + }, + "list-population-rule.floodlight-activity-id" => { + request_list_population_rule_init(&mut request); + request.list_population_rule.as_mut().unwrap().floodlight_activity_id = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_list_population_rule_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_list_population_rule_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "description" => { + request_list_population_rule_init(&mut request); + request.description = Some(value.unwrap_or("").to_string()); + }, + "list-size" => { + request_list_population_rule_init(&mut request); + request.list_size = Some(value.unwrap_or("").to_string()); + }, + "life-span" => { + request_list_population_rule_init(&mut request); + request.life_span = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_list_population_rule_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request_list_population_rule_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_list_population_rule_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "list-source" => { + request_advertiser_id_dimension_value_init(&mut request); + request.list_source = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "advertiser-id", "advertiser-id-dimension-value", "description", "dimension-name", "etag", "floodlight-activity-id", "floodlight-activity-name", "id", "kind", "life-span", "list-population-rule", "list-size", "list-source", "match-type", "name", "subaccount-id", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.remarketing_lists().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _remarketing_lists_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::RemarketingList::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_advertiser_id_dimension_value_init(request: &mut api::RemarketingList) { + if request.advertiser_id_dimension_value.is_none() { + request.advertiser_id_dimension_value = Some(Default::default()); + } + } + + fn request_list_population_rule_init(request: &mut api::RemarketingList) { + if request.list_population_rule.is_none() { + request.list_population_rule = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "list-population-rule.floodlight-activity-name" => { + request_list_population_rule_init(&mut request); + request.list_population_rule.as_mut().unwrap().floodlight_activity_name = Some(value.unwrap_or("").to_string()); + }, + "list-population-rule.floodlight-activity-id" => { + request_list_population_rule_init(&mut request); + request.list_population_rule.as_mut().unwrap().floodlight_activity_id = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_list_population_rule_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request_list_population_rule_init(&mut request); + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "description" => { + request_list_population_rule_init(&mut request); + request.description = Some(value.unwrap_or("").to_string()); + }, + "list-size" => { + request_list_population_rule_init(&mut request); + request.list_size = Some(value.unwrap_or("").to_string()); + }, + "life-span" => { + request_list_population_rule_init(&mut request); + request.life_span = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_list_population_rule_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id" => { + request_list_population_rule_init(&mut request); + request.advertiser_id = Some(value.unwrap_or("").to_string()); + }, + "active" => { + request_list_population_rule_init(&mut request); + request.active = Some(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + "advertiser-id-dimension-value.kind" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.value" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.dimension-name" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.etag" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.match-type" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "advertiser-id-dimension-value.id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.advertiser_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_advertiser_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "list-source" => { + request_advertiser_id_dimension_value_init(&mut request); + request.list_source = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "advertiser-id", "advertiser-id-dimension-value", "description", "dimension-name", "etag", "floodlight-activity-id", "floodlight-activity-name", "id", "kind", "life-span", "list-population-rule", "list-size", "list-source", "match-type", "name", "subaccount-id", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.remarketing_lists().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _reports_compatible_fields_query(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Report::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_criteria_activities_init(request: &mut api::Report) { + request_criteria_init(request); + if request.criteria.as_mut().unwrap().activities.is_none() { + request.criteria.as_mut().unwrap().activities = Some(Default::default()); + } + } + + fn request_criteria_custom_rich_media_events_init(request: &mut api::Report) { + request_criteria_init(request); + if request.criteria.as_mut().unwrap().custom_rich_media_events.is_none() { + request.criteria.as_mut().unwrap().custom_rich_media_events = Some(Default::default()); + } + } + + fn request_criteria_date_range_init(request: &mut api::Report) { + request_criteria_init(request); + if request.criteria.as_mut().unwrap().date_range.is_none() { + request.criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_criteria_init(request: &mut api::Report) { + if request.criteria.is_none() { + request.criteria = Some(Default::default()); + } + } + + fn request_cross_dimension_reach_criteria_date_range_init(request: &mut api::Report) { + request_cross_dimension_reach_criteria_init(request); + if request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.is_none() { + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_cross_dimension_reach_criteria_init(request: &mut api::Report) { + if request.cross_dimension_reach_criteria.is_none() { + request.cross_dimension_reach_criteria = Some(Default::default()); + } + } + + fn request_delivery_init(request: &mut api::Report) { + if request.delivery.is_none() { + request.delivery = Some(Default::default()); + } + } + + fn request_floodlight_criteria_date_range_init(request: &mut api::Report) { + request_floodlight_criteria_init(request); + if request.floodlight_criteria.as_mut().unwrap().date_range.is_none() { + request.floodlight_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_floodlight_criteria_floodlight_config_id_init(request: &mut api::Report) { + request_floodlight_criteria_init(request); + if request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.is_none() { + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id = Some(Default::default()); + } + } + + fn request_floodlight_criteria_init(request: &mut api::Report) { + if request.floodlight_criteria.is_none() { + request.floodlight_criteria = Some(Default::default()); + } + } + + fn request_floodlight_criteria_report_properties_init(request: &mut api::Report) { + request_floodlight_criteria_init(request); + if request.floodlight_criteria.as_mut().unwrap().report_properties.is_none() { + request.floodlight_criteria.as_mut().unwrap().report_properties = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_date_range_init(request: &mut api::Report) { + request_path_to_conversion_criteria_init(request); + if request.path_to_conversion_criteria.as_mut().unwrap().date_range.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_floodlight_config_id_init(request: &mut api::Report) { + request_path_to_conversion_criteria_init(request); + if request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_init(request: &mut api::Report) { + if request.path_to_conversion_criteria.is_none() { + request.path_to_conversion_criteria = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_report_properties_init(request: &mut api::Report) { + request_path_to_conversion_criteria_init(request); + if request.path_to_conversion_criteria.as_mut().unwrap().report_properties.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().report_properties = Some(Default::default()); + } + } + + fn request_reach_criteria_activities_init(request: &mut api::Report) { + request_reach_criteria_init(request); + if request.reach_criteria.as_mut().unwrap().activities.is_none() { + request.reach_criteria.as_mut().unwrap().activities = Some(Default::default()); + } + } + + fn request_reach_criteria_custom_rich_media_events_init(request: &mut api::Report) { + request_reach_criteria_init(request); + if request.reach_criteria.as_mut().unwrap().custom_rich_media_events.is_none() { + request.reach_criteria.as_mut().unwrap().custom_rich_media_events = Some(Default::default()); + } + } + + fn request_reach_criteria_date_range_init(request: &mut api::Report) { + request_reach_criteria_init(request); + if request.reach_criteria.as_mut().unwrap().date_range.is_none() { + request.reach_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_reach_criteria_init(request: &mut api::Report) { + if request.reach_criteria.is_none() { + request.reach_criteria = Some(Default::default()); + } + } + + fn request_schedule_init(request: &mut api::Report) { + if request.schedule.is_none() { + request.schedule = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "criteria.activities.kind" => { + request_criteria_activities_init(&mut request); + request.criteria.as_mut().unwrap().activities.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "criteria.activities.metric-names" => { + request_criteria_activities_init(&mut request); + if request.criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.is_none() { + request.criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "criteria.date-range.start-date" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "criteria.date-range.kind" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "criteria.date-range.end-date" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "criteria.date-range.relative-date-range" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "criteria.custom-rich-media-events.kind" => { + request_criteria_custom_rich_media_events_init(&mut request); + request.criteria.as_mut().unwrap().custom_rich_media_events.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "criteria.metric-names" => { + request_criteria_custom_rich_media_events_init(&mut request); + if request.criteria.as_mut().unwrap().metric_names.is_none() { + request.criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "kind" => { + request_criteria_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "sub-account-id" => { + request_criteria_init(&mut request); + request.sub_account_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_criteria_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "schedule.start-date" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "schedule.runs-on-day-of-month" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().runs_on_day_of_month = Some(value.unwrap_or("").to_string()); + }, + "schedule.every" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().every = Some(arg_from_str(value.unwrap_or("-0"), err, "schedule.every", "integer")); + }, + "schedule.expiration-date" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().expiration_date = Some(value.unwrap_or("").to_string()); + }, + "schedule.active" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().active = Some(arg_from_str(value.unwrap_or("false"), err, "schedule.active", "boolean")); + }, + "schedule.repeats" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().repeats = Some(value.unwrap_or("").to_string()); + }, + "schedule.repeats-on-week-days" => { + request_schedule_init(&mut request); + if request.schedule.as_mut().unwrap().repeats_on_week_days.is_none() { + request.schedule.as_mut().unwrap().repeats_on_week_days = Some(Default::default()); + } + request.schedule.as_mut().unwrap().repeats_on_week_days.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.start-date" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.kind" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.end-date" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.relative-date-range" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.kind" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.value" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.dimension-name" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.etag" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.match-type" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.id" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.report-properties.clicks-lookback-window" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().clicks_lookback_window = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.clicks-lookback-window", "integer")); + }, + "path-to-conversion-criteria.report-properties.pivot-on-interaction-path" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().pivot_on_interaction_path = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.pivot-on-interaction-path", "boolean")); + }, + "path-to-conversion-criteria.report-properties.impressions-lookback-window" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().impressions_lookback_window = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.impressions-lookback-window", "integer")); + }, + "path-to-conversion-criteria.report-properties.include-unattributed-ip-conversions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.include-unattributed-ip-conversions", "boolean")); + }, + "path-to-conversion-criteria.report-properties.include-unattributed-cookie-conversions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_cookie_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.include-unattributed-cookie-conversions", "boolean")); + }, + "path-to-conversion-criteria.report-properties.maximum-interaction-gap" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().maximum_interaction_gap = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.maximum-interaction-gap", "integer")); + }, + "path-to-conversion-criteria.report-properties.include-attributed-ip-conversions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_attributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.include-attributed-ip-conversions", "boolean")); + }, + "path-to-conversion-criteria.report-properties.maximum-click-interactions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().maximum_click_interactions = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.maximum-click-interactions", "integer")); + }, + "path-to-conversion-criteria.report-properties.maximum-impression-interactions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().maximum_impression_interactions = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.maximum-impression-interactions", "integer")); + }, + "path-to-conversion-criteria.metric-names" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + if request.path_to_conversion_criteria.as_mut().unwrap().metric_names.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.path_to_conversion_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "format" => { + request_path_to_conversion_criteria_init(&mut request); + request.format = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.activities.kind" => { + request_reach_criteria_activities_init(&mut request); + request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.activities.metric-names" => { + request_reach_criteria_activities_init(&mut request); + if request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.is_none() { + request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "reach-criteria.metric-names" => { + request_reach_criteria_activities_init(&mut request); + if request.reach_criteria.as_mut().unwrap().metric_names.is_none() { + request.reach_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.reach_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.start-date" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.kind" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.end-date" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.relative-date-range" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.reach-by-frequency-metric-names" => { + request_reach_criteria_date_range_init(&mut request); + if request.reach_criteria.as_mut().unwrap().reach_by_frequency_metric_names.is_none() { + request.reach_criteria.as_mut().unwrap().reach_by_frequency_metric_names = Some(Default::default()); + } + request.reach_criteria.as_mut().unwrap().reach_by_frequency_metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "reach-criteria.custom-rich-media-events.kind" => { + request_reach_criteria_custom_rich_media_events_init(&mut request); + request.reach_criteria.as_mut().unwrap().custom_rich_media_events.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.enable-all-dimension-combinations" => { + request_reach_criteria_custom_rich_media_events_init(&mut request); + request.reach_criteria.as_mut().unwrap().enable_all_dimension_combinations = Some(arg_from_str(value.unwrap_or("false"), err, "reach-criteria.enable-all-dimension-combinations", "boolean")); + }, + "file-name" => { + request_reach_criteria_init(&mut request); + request.file_name = Some(value.unwrap_or("").to_string()); + }, + "delivery.message" => { + request_delivery_init(&mut request); + request.delivery.as_mut().unwrap().message = Some(value.unwrap_or("").to_string()); + }, + "delivery.email-owner-delivery-type" => { + request_delivery_init(&mut request); + request.delivery.as_mut().unwrap().email_owner_delivery_type = Some(value.unwrap_or("").to_string()); + }, + "delivery.email-owner" => { + request_delivery_init(&mut request); + request.delivery.as_mut().unwrap().email_owner = Some(arg_from_str(value.unwrap_or("false"), err, "delivery.email-owner", "boolean")); + }, + "etag" => { + request_delivery_init(&mut request); + request.etag = Some(value.unwrap_or("").to_string()); + }, + "owner-profile-id" => { + request_delivery_init(&mut request); + request.owner_profile_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_delivery_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "last-modified-time" => { + request_delivery_init(&mut request); + request.last_modified_time = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_delivery_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "type" => { + request_delivery_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.start-date" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.kind" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.end-date" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.relative-date-range" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.kind" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.value" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.dimension-name" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.etag" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.match-type" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.id" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.report-properties.include-unattributed-ip-conversions" => { + request_floodlight_criteria_report_properties_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "floodlight-criteria.report-properties.include-unattributed-ip-conversions", "boolean")); + }, + "floodlight-criteria.report-properties.include-unattributed-cookie-conversions" => { + request_floodlight_criteria_report_properties_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_cookie_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "floodlight-criteria.report-properties.include-unattributed-cookie-conversions", "boolean")); + }, + "floodlight-criteria.report-properties.include-attributed-ip-conversions" => { + request_floodlight_criteria_report_properties_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_attributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "floodlight-criteria.report-properties.include-attributed-ip-conversions", "boolean")); + }, + "floodlight-criteria.metric-names" => { + request_floodlight_criteria_report_properties_init(&mut request); + if request.floodlight_criteria.as_mut().unwrap().metric_names.is_none() { + request.floodlight_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.floodlight_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.pivoted" => { + request_cross_dimension_reach_criteria_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().pivoted = Some(arg_from_str(value.unwrap_or("false"), err, "cross-dimension-reach-criteria.pivoted", "boolean")); + }, + "cross-dimension-reach-criteria.date-range.start-date" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.date-range.kind" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.date-range.end-date" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.date-range.relative-date-range" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.dimension" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().dimension = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.overlap-metric-names" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + if request.cross_dimension_reach_criteria.as_mut().unwrap().overlap_metric_names.is_none() { + request.cross_dimension_reach_criteria.as_mut().unwrap().overlap_metric_names = Some(Default::default()); + } + request.cross_dimension_reach_criteria.as_mut().unwrap().overlap_metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.metric-names" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + if request.cross_dimension_reach_criteria.as_mut().unwrap().metric_names.is_none() { + request.cross_dimension_reach_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.cross_dimension_reach_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "activities", "clicks-lookback-window", "criteria", "cross-dimension-reach-criteria", "custom-rich-media-events", "date-range", "delivery", "dimension", "dimension-name", "email-owner", "email-owner-delivery-type", "enable-all-dimension-combinations", "end-date", "etag", "every", "expiration-date", "file-name", "floodlight-config-id", "floodlight-criteria", "format", "id", "impressions-lookback-window", "include-attributed-ip-conversions", "include-unattributed-cookie-conversions", "include-unattributed-ip-conversions", "kind", "last-modified-time", "match-type", "maximum-click-interactions", "maximum-impression-interactions", "maximum-interaction-gap", "message", "metric-names", "name", "overlap-metric-names", "owner-profile-id", "path-to-conversion-criteria", "pivot-on-interaction-path", "pivoted", "reach-by-frequency-metric-names", "reach-criteria", "relative-date-range", "repeats", "repeats-on-week-days", "report-properties", "runs-on-day-of-month", "schedule", "start-date", "sub-account-id", "type", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.reports().compatible_fields_query(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _reports_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.reports().delete(opt.value_of("profile-id").unwrap_or(""), opt.value_of("report-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _reports_files_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut download_mode = false; + let mut call = self.hub.reports().files_get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("report-id").unwrap_or(""), opt.value_of("file-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + if !download_mode { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + } else { + io::copy(&mut response, &mut ostream).unwrap(); + } + Ok(()) + } + } + } + } + + fn _reports_files_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.reports().files_list(opt.value_of("profile-id").unwrap_or(""), opt.value_of("report-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sort-field", "sort-order", "max-results", "page-token"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _reports_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.reports().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("report-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _reports_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Report::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_criteria_activities_init(request: &mut api::Report) { + request_criteria_init(request); + if request.criteria.as_mut().unwrap().activities.is_none() { + request.criteria.as_mut().unwrap().activities = Some(Default::default()); + } + } + + fn request_criteria_custom_rich_media_events_init(request: &mut api::Report) { + request_criteria_init(request); + if request.criteria.as_mut().unwrap().custom_rich_media_events.is_none() { + request.criteria.as_mut().unwrap().custom_rich_media_events = Some(Default::default()); + } + } + + fn request_criteria_date_range_init(request: &mut api::Report) { + request_criteria_init(request); + if request.criteria.as_mut().unwrap().date_range.is_none() { + request.criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_criteria_init(request: &mut api::Report) { + if request.criteria.is_none() { + request.criteria = Some(Default::default()); + } + } + + fn request_cross_dimension_reach_criteria_date_range_init(request: &mut api::Report) { + request_cross_dimension_reach_criteria_init(request); + if request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.is_none() { + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_cross_dimension_reach_criteria_init(request: &mut api::Report) { + if request.cross_dimension_reach_criteria.is_none() { + request.cross_dimension_reach_criteria = Some(Default::default()); + } + } + + fn request_delivery_init(request: &mut api::Report) { + if request.delivery.is_none() { + request.delivery = Some(Default::default()); + } + } + + fn request_floodlight_criteria_date_range_init(request: &mut api::Report) { + request_floodlight_criteria_init(request); + if request.floodlight_criteria.as_mut().unwrap().date_range.is_none() { + request.floodlight_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_floodlight_criteria_floodlight_config_id_init(request: &mut api::Report) { + request_floodlight_criteria_init(request); + if request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.is_none() { + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id = Some(Default::default()); + } + } + + fn request_floodlight_criteria_init(request: &mut api::Report) { + if request.floodlight_criteria.is_none() { + request.floodlight_criteria = Some(Default::default()); + } + } + + fn request_floodlight_criteria_report_properties_init(request: &mut api::Report) { + request_floodlight_criteria_init(request); + if request.floodlight_criteria.as_mut().unwrap().report_properties.is_none() { + request.floodlight_criteria.as_mut().unwrap().report_properties = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_date_range_init(request: &mut api::Report) { + request_path_to_conversion_criteria_init(request); + if request.path_to_conversion_criteria.as_mut().unwrap().date_range.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_floodlight_config_id_init(request: &mut api::Report) { + request_path_to_conversion_criteria_init(request); + if request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_init(request: &mut api::Report) { + if request.path_to_conversion_criteria.is_none() { + request.path_to_conversion_criteria = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_report_properties_init(request: &mut api::Report) { + request_path_to_conversion_criteria_init(request); + if request.path_to_conversion_criteria.as_mut().unwrap().report_properties.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().report_properties = Some(Default::default()); + } + } + + fn request_reach_criteria_activities_init(request: &mut api::Report) { + request_reach_criteria_init(request); + if request.reach_criteria.as_mut().unwrap().activities.is_none() { + request.reach_criteria.as_mut().unwrap().activities = Some(Default::default()); + } + } + + fn request_reach_criteria_custom_rich_media_events_init(request: &mut api::Report) { + request_reach_criteria_init(request); + if request.reach_criteria.as_mut().unwrap().custom_rich_media_events.is_none() { + request.reach_criteria.as_mut().unwrap().custom_rich_media_events = Some(Default::default()); + } + } + + fn request_reach_criteria_date_range_init(request: &mut api::Report) { + request_reach_criteria_init(request); + if request.reach_criteria.as_mut().unwrap().date_range.is_none() { + request.reach_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_reach_criteria_init(request: &mut api::Report) { + if request.reach_criteria.is_none() { + request.reach_criteria = Some(Default::default()); + } + } + + fn request_schedule_init(request: &mut api::Report) { + if request.schedule.is_none() { + request.schedule = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "criteria.activities.kind" => { + request_criteria_activities_init(&mut request); + request.criteria.as_mut().unwrap().activities.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "criteria.activities.metric-names" => { + request_criteria_activities_init(&mut request); + if request.criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.is_none() { + request.criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "criteria.date-range.start-date" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "criteria.date-range.kind" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "criteria.date-range.end-date" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "criteria.date-range.relative-date-range" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "criteria.custom-rich-media-events.kind" => { + request_criteria_custom_rich_media_events_init(&mut request); + request.criteria.as_mut().unwrap().custom_rich_media_events.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "criteria.metric-names" => { + request_criteria_custom_rich_media_events_init(&mut request); + if request.criteria.as_mut().unwrap().metric_names.is_none() { + request.criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "kind" => { + request_criteria_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "sub-account-id" => { + request_criteria_init(&mut request); + request.sub_account_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_criteria_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "schedule.start-date" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "schedule.runs-on-day-of-month" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().runs_on_day_of_month = Some(value.unwrap_or("").to_string()); + }, + "schedule.every" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().every = Some(arg_from_str(value.unwrap_or("-0"), err, "schedule.every", "integer")); + }, + "schedule.expiration-date" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().expiration_date = Some(value.unwrap_or("").to_string()); + }, + "schedule.active" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().active = Some(arg_from_str(value.unwrap_or("false"), err, "schedule.active", "boolean")); + }, + "schedule.repeats" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().repeats = Some(value.unwrap_or("").to_string()); + }, + "schedule.repeats-on-week-days" => { + request_schedule_init(&mut request); + if request.schedule.as_mut().unwrap().repeats_on_week_days.is_none() { + request.schedule.as_mut().unwrap().repeats_on_week_days = Some(Default::default()); + } + request.schedule.as_mut().unwrap().repeats_on_week_days.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.start-date" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.kind" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.end-date" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.relative-date-range" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.kind" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.value" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.dimension-name" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.etag" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.match-type" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.id" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.report-properties.clicks-lookback-window" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().clicks_lookback_window = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.clicks-lookback-window", "integer")); + }, + "path-to-conversion-criteria.report-properties.pivot-on-interaction-path" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().pivot_on_interaction_path = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.pivot-on-interaction-path", "boolean")); + }, + "path-to-conversion-criteria.report-properties.impressions-lookback-window" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().impressions_lookback_window = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.impressions-lookback-window", "integer")); + }, + "path-to-conversion-criteria.report-properties.include-unattributed-ip-conversions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.include-unattributed-ip-conversions", "boolean")); + }, + "path-to-conversion-criteria.report-properties.include-unattributed-cookie-conversions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_cookie_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.include-unattributed-cookie-conversions", "boolean")); + }, + "path-to-conversion-criteria.report-properties.maximum-interaction-gap" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().maximum_interaction_gap = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.maximum-interaction-gap", "integer")); + }, + "path-to-conversion-criteria.report-properties.include-attributed-ip-conversions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_attributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.include-attributed-ip-conversions", "boolean")); + }, + "path-to-conversion-criteria.report-properties.maximum-click-interactions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().maximum_click_interactions = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.maximum-click-interactions", "integer")); + }, + "path-to-conversion-criteria.report-properties.maximum-impression-interactions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().maximum_impression_interactions = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.maximum-impression-interactions", "integer")); + }, + "path-to-conversion-criteria.metric-names" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + if request.path_to_conversion_criteria.as_mut().unwrap().metric_names.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.path_to_conversion_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "format" => { + request_path_to_conversion_criteria_init(&mut request); + request.format = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.activities.kind" => { + request_reach_criteria_activities_init(&mut request); + request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.activities.metric-names" => { + request_reach_criteria_activities_init(&mut request); + if request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.is_none() { + request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "reach-criteria.metric-names" => { + request_reach_criteria_activities_init(&mut request); + if request.reach_criteria.as_mut().unwrap().metric_names.is_none() { + request.reach_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.reach_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.start-date" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.kind" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.end-date" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.relative-date-range" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.reach-by-frequency-metric-names" => { + request_reach_criteria_date_range_init(&mut request); + if request.reach_criteria.as_mut().unwrap().reach_by_frequency_metric_names.is_none() { + request.reach_criteria.as_mut().unwrap().reach_by_frequency_metric_names = Some(Default::default()); + } + request.reach_criteria.as_mut().unwrap().reach_by_frequency_metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "reach-criteria.custom-rich-media-events.kind" => { + request_reach_criteria_custom_rich_media_events_init(&mut request); + request.reach_criteria.as_mut().unwrap().custom_rich_media_events.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.enable-all-dimension-combinations" => { + request_reach_criteria_custom_rich_media_events_init(&mut request); + request.reach_criteria.as_mut().unwrap().enable_all_dimension_combinations = Some(arg_from_str(value.unwrap_or("false"), err, "reach-criteria.enable-all-dimension-combinations", "boolean")); + }, + "file-name" => { + request_reach_criteria_init(&mut request); + request.file_name = Some(value.unwrap_or("").to_string()); + }, + "delivery.message" => { + request_delivery_init(&mut request); + request.delivery.as_mut().unwrap().message = Some(value.unwrap_or("").to_string()); + }, + "delivery.email-owner-delivery-type" => { + request_delivery_init(&mut request); + request.delivery.as_mut().unwrap().email_owner_delivery_type = Some(value.unwrap_or("").to_string()); + }, + "delivery.email-owner" => { + request_delivery_init(&mut request); + request.delivery.as_mut().unwrap().email_owner = Some(arg_from_str(value.unwrap_or("false"), err, "delivery.email-owner", "boolean")); + }, + "etag" => { + request_delivery_init(&mut request); + request.etag = Some(value.unwrap_or("").to_string()); + }, + "owner-profile-id" => { + request_delivery_init(&mut request); + request.owner_profile_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_delivery_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "last-modified-time" => { + request_delivery_init(&mut request); + request.last_modified_time = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_delivery_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "type" => { + request_delivery_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.start-date" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.kind" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.end-date" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.relative-date-range" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.kind" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.value" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.dimension-name" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.etag" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.match-type" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.id" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.report-properties.include-unattributed-ip-conversions" => { + request_floodlight_criteria_report_properties_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "floodlight-criteria.report-properties.include-unattributed-ip-conversions", "boolean")); + }, + "floodlight-criteria.report-properties.include-unattributed-cookie-conversions" => { + request_floodlight_criteria_report_properties_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_cookie_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "floodlight-criteria.report-properties.include-unattributed-cookie-conversions", "boolean")); + }, + "floodlight-criteria.report-properties.include-attributed-ip-conversions" => { + request_floodlight_criteria_report_properties_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_attributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "floodlight-criteria.report-properties.include-attributed-ip-conversions", "boolean")); + }, + "floodlight-criteria.metric-names" => { + request_floodlight_criteria_report_properties_init(&mut request); + if request.floodlight_criteria.as_mut().unwrap().metric_names.is_none() { + request.floodlight_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.floodlight_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.pivoted" => { + request_cross_dimension_reach_criteria_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().pivoted = Some(arg_from_str(value.unwrap_or("false"), err, "cross-dimension-reach-criteria.pivoted", "boolean")); + }, + "cross-dimension-reach-criteria.date-range.start-date" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.date-range.kind" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.date-range.end-date" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.date-range.relative-date-range" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.dimension" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().dimension = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.overlap-metric-names" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + if request.cross_dimension_reach_criteria.as_mut().unwrap().overlap_metric_names.is_none() { + request.cross_dimension_reach_criteria.as_mut().unwrap().overlap_metric_names = Some(Default::default()); + } + request.cross_dimension_reach_criteria.as_mut().unwrap().overlap_metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.metric-names" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + if request.cross_dimension_reach_criteria.as_mut().unwrap().metric_names.is_none() { + request.cross_dimension_reach_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.cross_dimension_reach_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "activities", "clicks-lookback-window", "criteria", "cross-dimension-reach-criteria", "custom-rich-media-events", "date-range", "delivery", "dimension", "dimension-name", "email-owner", "email-owner-delivery-type", "enable-all-dimension-combinations", "end-date", "etag", "every", "expiration-date", "file-name", "floodlight-config-id", "floodlight-criteria", "format", "id", "impressions-lookback-window", "include-attributed-ip-conversions", "include-unattributed-cookie-conversions", "include-unattributed-ip-conversions", "kind", "last-modified-time", "match-type", "maximum-click-interactions", "maximum-impression-interactions", "maximum-interaction-gap", "message", "metric-names", "name", "overlap-metric-names", "owner-profile-id", "path-to-conversion-criteria", "pivot-on-interaction-path", "pivoted", "reach-by-frequency-metric-names", "reach-criteria", "relative-date-range", "repeats", "repeats-on-week-days", "report-properties", "runs-on-day-of-month", "schedule", "start-date", "sub-account-id", "type", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.reports().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _reports_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.reports().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "scope" => { + call = call.scope(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sort-field", "max-results", "sort-order", "page-token", "scope"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _reports_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Report::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_criteria_activities_init(request: &mut api::Report) { + request_criteria_init(request); + if request.criteria.as_mut().unwrap().activities.is_none() { + request.criteria.as_mut().unwrap().activities = Some(Default::default()); + } + } + + fn request_criteria_custom_rich_media_events_init(request: &mut api::Report) { + request_criteria_init(request); + if request.criteria.as_mut().unwrap().custom_rich_media_events.is_none() { + request.criteria.as_mut().unwrap().custom_rich_media_events = Some(Default::default()); + } + } + + fn request_criteria_date_range_init(request: &mut api::Report) { + request_criteria_init(request); + if request.criteria.as_mut().unwrap().date_range.is_none() { + request.criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_criteria_init(request: &mut api::Report) { + if request.criteria.is_none() { + request.criteria = Some(Default::default()); + } + } + + fn request_cross_dimension_reach_criteria_date_range_init(request: &mut api::Report) { + request_cross_dimension_reach_criteria_init(request); + if request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.is_none() { + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_cross_dimension_reach_criteria_init(request: &mut api::Report) { + if request.cross_dimension_reach_criteria.is_none() { + request.cross_dimension_reach_criteria = Some(Default::default()); + } + } + + fn request_delivery_init(request: &mut api::Report) { + if request.delivery.is_none() { + request.delivery = Some(Default::default()); + } + } + + fn request_floodlight_criteria_date_range_init(request: &mut api::Report) { + request_floodlight_criteria_init(request); + if request.floodlight_criteria.as_mut().unwrap().date_range.is_none() { + request.floodlight_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_floodlight_criteria_floodlight_config_id_init(request: &mut api::Report) { + request_floodlight_criteria_init(request); + if request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.is_none() { + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id = Some(Default::default()); + } + } + + fn request_floodlight_criteria_init(request: &mut api::Report) { + if request.floodlight_criteria.is_none() { + request.floodlight_criteria = Some(Default::default()); + } + } + + fn request_floodlight_criteria_report_properties_init(request: &mut api::Report) { + request_floodlight_criteria_init(request); + if request.floodlight_criteria.as_mut().unwrap().report_properties.is_none() { + request.floodlight_criteria.as_mut().unwrap().report_properties = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_date_range_init(request: &mut api::Report) { + request_path_to_conversion_criteria_init(request); + if request.path_to_conversion_criteria.as_mut().unwrap().date_range.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_floodlight_config_id_init(request: &mut api::Report) { + request_path_to_conversion_criteria_init(request); + if request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_init(request: &mut api::Report) { + if request.path_to_conversion_criteria.is_none() { + request.path_to_conversion_criteria = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_report_properties_init(request: &mut api::Report) { + request_path_to_conversion_criteria_init(request); + if request.path_to_conversion_criteria.as_mut().unwrap().report_properties.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().report_properties = Some(Default::default()); + } + } + + fn request_reach_criteria_activities_init(request: &mut api::Report) { + request_reach_criteria_init(request); + if request.reach_criteria.as_mut().unwrap().activities.is_none() { + request.reach_criteria.as_mut().unwrap().activities = Some(Default::default()); + } + } + + fn request_reach_criteria_custom_rich_media_events_init(request: &mut api::Report) { + request_reach_criteria_init(request); + if request.reach_criteria.as_mut().unwrap().custom_rich_media_events.is_none() { + request.reach_criteria.as_mut().unwrap().custom_rich_media_events = Some(Default::default()); + } + } + + fn request_reach_criteria_date_range_init(request: &mut api::Report) { + request_reach_criteria_init(request); + if request.reach_criteria.as_mut().unwrap().date_range.is_none() { + request.reach_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_reach_criteria_init(request: &mut api::Report) { + if request.reach_criteria.is_none() { + request.reach_criteria = Some(Default::default()); + } + } + + fn request_schedule_init(request: &mut api::Report) { + if request.schedule.is_none() { + request.schedule = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "criteria.activities.kind" => { + request_criteria_activities_init(&mut request); + request.criteria.as_mut().unwrap().activities.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "criteria.activities.metric-names" => { + request_criteria_activities_init(&mut request); + if request.criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.is_none() { + request.criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "criteria.date-range.start-date" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "criteria.date-range.kind" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "criteria.date-range.end-date" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "criteria.date-range.relative-date-range" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "criteria.custom-rich-media-events.kind" => { + request_criteria_custom_rich_media_events_init(&mut request); + request.criteria.as_mut().unwrap().custom_rich_media_events.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "criteria.metric-names" => { + request_criteria_custom_rich_media_events_init(&mut request); + if request.criteria.as_mut().unwrap().metric_names.is_none() { + request.criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "kind" => { + request_criteria_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "sub-account-id" => { + request_criteria_init(&mut request); + request.sub_account_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_criteria_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "schedule.start-date" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "schedule.runs-on-day-of-month" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().runs_on_day_of_month = Some(value.unwrap_or("").to_string()); + }, + "schedule.every" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().every = Some(arg_from_str(value.unwrap_or("-0"), err, "schedule.every", "integer")); + }, + "schedule.expiration-date" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().expiration_date = Some(value.unwrap_or("").to_string()); + }, + "schedule.active" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().active = Some(arg_from_str(value.unwrap_or("false"), err, "schedule.active", "boolean")); + }, + "schedule.repeats" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().repeats = Some(value.unwrap_or("").to_string()); + }, + "schedule.repeats-on-week-days" => { + request_schedule_init(&mut request); + if request.schedule.as_mut().unwrap().repeats_on_week_days.is_none() { + request.schedule.as_mut().unwrap().repeats_on_week_days = Some(Default::default()); + } + request.schedule.as_mut().unwrap().repeats_on_week_days.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.start-date" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.kind" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.end-date" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.relative-date-range" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.kind" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.value" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.dimension-name" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.etag" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.match-type" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.id" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.report-properties.clicks-lookback-window" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().clicks_lookback_window = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.clicks-lookback-window", "integer")); + }, + "path-to-conversion-criteria.report-properties.pivot-on-interaction-path" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().pivot_on_interaction_path = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.pivot-on-interaction-path", "boolean")); + }, + "path-to-conversion-criteria.report-properties.impressions-lookback-window" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().impressions_lookback_window = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.impressions-lookback-window", "integer")); + }, + "path-to-conversion-criteria.report-properties.include-unattributed-ip-conversions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.include-unattributed-ip-conversions", "boolean")); + }, + "path-to-conversion-criteria.report-properties.include-unattributed-cookie-conversions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_cookie_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.include-unattributed-cookie-conversions", "boolean")); + }, + "path-to-conversion-criteria.report-properties.maximum-interaction-gap" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().maximum_interaction_gap = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.maximum-interaction-gap", "integer")); + }, + "path-to-conversion-criteria.report-properties.include-attributed-ip-conversions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_attributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.include-attributed-ip-conversions", "boolean")); + }, + "path-to-conversion-criteria.report-properties.maximum-click-interactions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().maximum_click_interactions = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.maximum-click-interactions", "integer")); + }, + "path-to-conversion-criteria.report-properties.maximum-impression-interactions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().maximum_impression_interactions = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.maximum-impression-interactions", "integer")); + }, + "path-to-conversion-criteria.metric-names" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + if request.path_to_conversion_criteria.as_mut().unwrap().metric_names.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.path_to_conversion_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "format" => { + request_path_to_conversion_criteria_init(&mut request); + request.format = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.activities.kind" => { + request_reach_criteria_activities_init(&mut request); + request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.activities.metric-names" => { + request_reach_criteria_activities_init(&mut request); + if request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.is_none() { + request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "reach-criteria.metric-names" => { + request_reach_criteria_activities_init(&mut request); + if request.reach_criteria.as_mut().unwrap().metric_names.is_none() { + request.reach_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.reach_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.start-date" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.kind" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.end-date" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.relative-date-range" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.reach-by-frequency-metric-names" => { + request_reach_criteria_date_range_init(&mut request); + if request.reach_criteria.as_mut().unwrap().reach_by_frequency_metric_names.is_none() { + request.reach_criteria.as_mut().unwrap().reach_by_frequency_metric_names = Some(Default::default()); + } + request.reach_criteria.as_mut().unwrap().reach_by_frequency_metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "reach-criteria.custom-rich-media-events.kind" => { + request_reach_criteria_custom_rich_media_events_init(&mut request); + request.reach_criteria.as_mut().unwrap().custom_rich_media_events.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.enable-all-dimension-combinations" => { + request_reach_criteria_custom_rich_media_events_init(&mut request); + request.reach_criteria.as_mut().unwrap().enable_all_dimension_combinations = Some(arg_from_str(value.unwrap_or("false"), err, "reach-criteria.enable-all-dimension-combinations", "boolean")); + }, + "file-name" => { + request_reach_criteria_init(&mut request); + request.file_name = Some(value.unwrap_or("").to_string()); + }, + "delivery.message" => { + request_delivery_init(&mut request); + request.delivery.as_mut().unwrap().message = Some(value.unwrap_or("").to_string()); + }, + "delivery.email-owner-delivery-type" => { + request_delivery_init(&mut request); + request.delivery.as_mut().unwrap().email_owner_delivery_type = Some(value.unwrap_or("").to_string()); + }, + "delivery.email-owner" => { + request_delivery_init(&mut request); + request.delivery.as_mut().unwrap().email_owner = Some(arg_from_str(value.unwrap_or("false"), err, "delivery.email-owner", "boolean")); + }, + "etag" => { + request_delivery_init(&mut request); + request.etag = Some(value.unwrap_or("").to_string()); + }, + "owner-profile-id" => { + request_delivery_init(&mut request); + request.owner_profile_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_delivery_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "last-modified-time" => { + request_delivery_init(&mut request); + request.last_modified_time = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_delivery_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "type" => { + request_delivery_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.start-date" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.kind" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.end-date" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.relative-date-range" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.kind" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.value" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.dimension-name" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.etag" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.match-type" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.id" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.report-properties.include-unattributed-ip-conversions" => { + request_floodlight_criteria_report_properties_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "floodlight-criteria.report-properties.include-unattributed-ip-conversions", "boolean")); + }, + "floodlight-criteria.report-properties.include-unattributed-cookie-conversions" => { + request_floodlight_criteria_report_properties_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_cookie_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "floodlight-criteria.report-properties.include-unattributed-cookie-conversions", "boolean")); + }, + "floodlight-criteria.report-properties.include-attributed-ip-conversions" => { + request_floodlight_criteria_report_properties_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_attributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "floodlight-criteria.report-properties.include-attributed-ip-conversions", "boolean")); + }, + "floodlight-criteria.metric-names" => { + request_floodlight_criteria_report_properties_init(&mut request); + if request.floodlight_criteria.as_mut().unwrap().metric_names.is_none() { + request.floodlight_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.floodlight_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.pivoted" => { + request_cross_dimension_reach_criteria_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().pivoted = Some(arg_from_str(value.unwrap_or("false"), err, "cross-dimension-reach-criteria.pivoted", "boolean")); + }, + "cross-dimension-reach-criteria.date-range.start-date" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.date-range.kind" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.date-range.end-date" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.date-range.relative-date-range" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.dimension" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().dimension = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.overlap-metric-names" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + if request.cross_dimension_reach_criteria.as_mut().unwrap().overlap_metric_names.is_none() { + request.cross_dimension_reach_criteria.as_mut().unwrap().overlap_metric_names = Some(Default::default()); + } + request.cross_dimension_reach_criteria.as_mut().unwrap().overlap_metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.metric-names" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + if request.cross_dimension_reach_criteria.as_mut().unwrap().metric_names.is_none() { + request.cross_dimension_reach_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.cross_dimension_reach_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "activities", "clicks-lookback-window", "criteria", "cross-dimension-reach-criteria", "custom-rich-media-events", "date-range", "delivery", "dimension", "dimension-name", "email-owner", "email-owner-delivery-type", "enable-all-dimension-combinations", "end-date", "etag", "every", "expiration-date", "file-name", "floodlight-config-id", "floodlight-criteria", "format", "id", "impressions-lookback-window", "include-attributed-ip-conversions", "include-unattributed-cookie-conversions", "include-unattributed-ip-conversions", "kind", "last-modified-time", "match-type", "maximum-click-interactions", "maximum-impression-interactions", "maximum-interaction-gap", "message", "metric-names", "name", "overlap-metric-names", "owner-profile-id", "path-to-conversion-criteria", "pivot-on-interaction-path", "pivoted", "reach-by-frequency-metric-names", "reach-criteria", "relative-date-range", "repeats", "repeats-on-week-days", "report-properties", "runs-on-day-of-month", "schedule", "start-date", "sub-account-id", "type", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.reports().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("report-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _reports_run(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.reports().run(opt.value_of("profile-id").unwrap_or(""), opt.value_of("report-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "synchronous" => { + call = call.synchronous(arg_from_str(value.unwrap_or("false"), err, "synchronous", "boolean")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["synchronous"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _reports_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Report::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_criteria_activities_init(request: &mut api::Report) { + request_criteria_init(request); + if request.criteria.as_mut().unwrap().activities.is_none() { + request.criteria.as_mut().unwrap().activities = Some(Default::default()); + } + } + + fn request_criteria_custom_rich_media_events_init(request: &mut api::Report) { + request_criteria_init(request); + if request.criteria.as_mut().unwrap().custom_rich_media_events.is_none() { + request.criteria.as_mut().unwrap().custom_rich_media_events = Some(Default::default()); + } + } + + fn request_criteria_date_range_init(request: &mut api::Report) { + request_criteria_init(request); + if request.criteria.as_mut().unwrap().date_range.is_none() { + request.criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_criteria_init(request: &mut api::Report) { + if request.criteria.is_none() { + request.criteria = Some(Default::default()); + } + } + + fn request_cross_dimension_reach_criteria_date_range_init(request: &mut api::Report) { + request_cross_dimension_reach_criteria_init(request); + if request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.is_none() { + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_cross_dimension_reach_criteria_init(request: &mut api::Report) { + if request.cross_dimension_reach_criteria.is_none() { + request.cross_dimension_reach_criteria = Some(Default::default()); + } + } + + fn request_delivery_init(request: &mut api::Report) { + if request.delivery.is_none() { + request.delivery = Some(Default::default()); + } + } + + fn request_floodlight_criteria_date_range_init(request: &mut api::Report) { + request_floodlight_criteria_init(request); + if request.floodlight_criteria.as_mut().unwrap().date_range.is_none() { + request.floodlight_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_floodlight_criteria_floodlight_config_id_init(request: &mut api::Report) { + request_floodlight_criteria_init(request); + if request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.is_none() { + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id = Some(Default::default()); + } + } + + fn request_floodlight_criteria_init(request: &mut api::Report) { + if request.floodlight_criteria.is_none() { + request.floodlight_criteria = Some(Default::default()); + } + } + + fn request_floodlight_criteria_report_properties_init(request: &mut api::Report) { + request_floodlight_criteria_init(request); + if request.floodlight_criteria.as_mut().unwrap().report_properties.is_none() { + request.floodlight_criteria.as_mut().unwrap().report_properties = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_date_range_init(request: &mut api::Report) { + request_path_to_conversion_criteria_init(request); + if request.path_to_conversion_criteria.as_mut().unwrap().date_range.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_floodlight_config_id_init(request: &mut api::Report) { + request_path_to_conversion_criteria_init(request); + if request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_init(request: &mut api::Report) { + if request.path_to_conversion_criteria.is_none() { + request.path_to_conversion_criteria = Some(Default::default()); + } + } + + fn request_path_to_conversion_criteria_report_properties_init(request: &mut api::Report) { + request_path_to_conversion_criteria_init(request); + if request.path_to_conversion_criteria.as_mut().unwrap().report_properties.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().report_properties = Some(Default::default()); + } + } + + fn request_reach_criteria_activities_init(request: &mut api::Report) { + request_reach_criteria_init(request); + if request.reach_criteria.as_mut().unwrap().activities.is_none() { + request.reach_criteria.as_mut().unwrap().activities = Some(Default::default()); + } + } + + fn request_reach_criteria_custom_rich_media_events_init(request: &mut api::Report) { + request_reach_criteria_init(request); + if request.reach_criteria.as_mut().unwrap().custom_rich_media_events.is_none() { + request.reach_criteria.as_mut().unwrap().custom_rich_media_events = Some(Default::default()); + } + } + + fn request_reach_criteria_date_range_init(request: &mut api::Report) { + request_reach_criteria_init(request); + if request.reach_criteria.as_mut().unwrap().date_range.is_none() { + request.reach_criteria.as_mut().unwrap().date_range = Some(Default::default()); + } + } + + fn request_reach_criteria_init(request: &mut api::Report) { + if request.reach_criteria.is_none() { + request.reach_criteria = Some(Default::default()); + } + } + + fn request_schedule_init(request: &mut api::Report) { + if request.schedule.is_none() { + request.schedule = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "criteria.activities.kind" => { + request_criteria_activities_init(&mut request); + request.criteria.as_mut().unwrap().activities.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "criteria.activities.metric-names" => { + request_criteria_activities_init(&mut request); + if request.criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.is_none() { + request.criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "criteria.date-range.start-date" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "criteria.date-range.kind" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "criteria.date-range.end-date" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "criteria.date-range.relative-date-range" => { + request_criteria_date_range_init(&mut request); + request.criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "criteria.custom-rich-media-events.kind" => { + request_criteria_custom_rich_media_events_init(&mut request); + request.criteria.as_mut().unwrap().custom_rich_media_events.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "criteria.metric-names" => { + request_criteria_custom_rich_media_events_init(&mut request); + if request.criteria.as_mut().unwrap().metric_names.is_none() { + request.criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "kind" => { + request_criteria_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "sub-account-id" => { + request_criteria_init(&mut request); + request.sub_account_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request_criteria_init(&mut request); + request.name = Some(value.unwrap_or("").to_string()); + }, + "schedule.start-date" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "schedule.runs-on-day-of-month" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().runs_on_day_of_month = Some(value.unwrap_or("").to_string()); + }, + "schedule.every" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().every = Some(arg_from_str(value.unwrap_or("-0"), err, "schedule.every", "integer")); + }, + "schedule.expiration-date" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().expiration_date = Some(value.unwrap_or("").to_string()); + }, + "schedule.active" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().active = Some(arg_from_str(value.unwrap_or("false"), err, "schedule.active", "boolean")); + }, + "schedule.repeats" => { + request_schedule_init(&mut request); + request.schedule.as_mut().unwrap().repeats = Some(value.unwrap_or("").to_string()); + }, + "schedule.repeats-on-week-days" => { + request_schedule_init(&mut request); + if request.schedule.as_mut().unwrap().repeats_on_week_days.is_none() { + request.schedule.as_mut().unwrap().repeats_on_week_days = Some(Default::default()); + } + request.schedule.as_mut().unwrap().repeats_on_week_days.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.start-date" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.kind" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.end-date" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.date-range.relative-date-range" => { + request_path_to_conversion_criteria_date_range_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.kind" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.value" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.dimension-name" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.etag" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.match-type" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.floodlight-config-id.id" => { + request_path_to_conversion_criteria_floodlight_config_id_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "path-to-conversion-criteria.report-properties.clicks-lookback-window" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().clicks_lookback_window = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.clicks-lookback-window", "integer")); + }, + "path-to-conversion-criteria.report-properties.pivot-on-interaction-path" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().pivot_on_interaction_path = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.pivot-on-interaction-path", "boolean")); + }, + "path-to-conversion-criteria.report-properties.impressions-lookback-window" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().impressions_lookback_window = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.impressions-lookback-window", "integer")); + }, + "path-to-conversion-criteria.report-properties.include-unattributed-ip-conversions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.include-unattributed-ip-conversions", "boolean")); + }, + "path-to-conversion-criteria.report-properties.include-unattributed-cookie-conversions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_cookie_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.include-unattributed-cookie-conversions", "boolean")); + }, + "path-to-conversion-criteria.report-properties.maximum-interaction-gap" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().maximum_interaction_gap = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.maximum-interaction-gap", "integer")); + }, + "path-to-conversion-criteria.report-properties.include-attributed-ip-conversions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_attributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "path-to-conversion-criteria.report-properties.include-attributed-ip-conversions", "boolean")); + }, + "path-to-conversion-criteria.report-properties.maximum-click-interactions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().maximum_click_interactions = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.maximum-click-interactions", "integer")); + }, + "path-to-conversion-criteria.report-properties.maximum-impression-interactions" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + request.path_to_conversion_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().maximum_impression_interactions = Some(arg_from_str(value.unwrap_or("-0"), err, "path-to-conversion-criteria.report-properties.maximum-impression-interactions", "integer")); + }, + "path-to-conversion-criteria.metric-names" => { + request_path_to_conversion_criteria_report_properties_init(&mut request); + if request.path_to_conversion_criteria.as_mut().unwrap().metric_names.is_none() { + request.path_to_conversion_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.path_to_conversion_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "format" => { + request_path_to_conversion_criteria_init(&mut request); + request.format = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.activities.kind" => { + request_reach_criteria_activities_init(&mut request); + request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.activities.metric-names" => { + request_reach_criteria_activities_init(&mut request); + if request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.is_none() { + request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.reach_criteria.as_mut().unwrap().activities.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "reach-criteria.metric-names" => { + request_reach_criteria_activities_init(&mut request); + if request.reach_criteria.as_mut().unwrap().metric_names.is_none() { + request.reach_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.reach_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.start-date" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.kind" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.end-date" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.date-range.relative-date-range" => { + request_reach_criteria_date_range_init(&mut request); + request.reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.reach-by-frequency-metric-names" => { + request_reach_criteria_date_range_init(&mut request); + if request.reach_criteria.as_mut().unwrap().reach_by_frequency_metric_names.is_none() { + request.reach_criteria.as_mut().unwrap().reach_by_frequency_metric_names = Some(Default::default()); + } + request.reach_criteria.as_mut().unwrap().reach_by_frequency_metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "reach-criteria.custom-rich-media-events.kind" => { + request_reach_criteria_custom_rich_media_events_init(&mut request); + request.reach_criteria.as_mut().unwrap().custom_rich_media_events.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "reach-criteria.enable-all-dimension-combinations" => { + request_reach_criteria_custom_rich_media_events_init(&mut request); + request.reach_criteria.as_mut().unwrap().enable_all_dimension_combinations = Some(arg_from_str(value.unwrap_or("false"), err, "reach-criteria.enable-all-dimension-combinations", "boolean")); + }, + "file-name" => { + request_reach_criteria_init(&mut request); + request.file_name = Some(value.unwrap_or("").to_string()); + }, + "delivery.message" => { + request_delivery_init(&mut request); + request.delivery.as_mut().unwrap().message = Some(value.unwrap_or("").to_string()); + }, + "delivery.email-owner-delivery-type" => { + request_delivery_init(&mut request); + request.delivery.as_mut().unwrap().email_owner_delivery_type = Some(value.unwrap_or("").to_string()); + }, + "delivery.email-owner" => { + request_delivery_init(&mut request); + request.delivery.as_mut().unwrap().email_owner = Some(arg_from_str(value.unwrap_or("false"), err, "delivery.email-owner", "boolean")); + }, + "etag" => { + request_delivery_init(&mut request); + request.etag = Some(value.unwrap_or("").to_string()); + }, + "owner-profile-id" => { + request_delivery_init(&mut request); + request.owner_profile_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_delivery_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "last-modified-time" => { + request_delivery_init(&mut request); + request.last_modified_time = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_delivery_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + "type" => { + request_delivery_init(&mut request); + request.type_ = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.start-date" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.kind" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.end-date" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.date-range.relative-date-range" => { + request_floodlight_criteria_date_range_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.kind" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.value" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.dimension-name" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.etag" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.match-type" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.floodlight-config-id.id" => { + request_floodlight_criteria_floodlight_config_id_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().floodlight_config_id.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "floodlight-criteria.report-properties.include-unattributed-ip-conversions" => { + request_floodlight_criteria_report_properties_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "floodlight-criteria.report-properties.include-unattributed-ip-conversions", "boolean")); + }, + "floodlight-criteria.report-properties.include-unattributed-cookie-conversions" => { + request_floodlight_criteria_report_properties_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_unattributed_cookie_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "floodlight-criteria.report-properties.include-unattributed-cookie-conversions", "boolean")); + }, + "floodlight-criteria.report-properties.include-attributed-ip-conversions" => { + request_floodlight_criteria_report_properties_init(&mut request); + request.floodlight_criteria.as_mut().unwrap().report_properties.as_mut().unwrap().include_attributed_ip_conversions = Some(arg_from_str(value.unwrap_or("false"), err, "floodlight-criteria.report-properties.include-attributed-ip-conversions", "boolean")); + }, + "floodlight-criteria.metric-names" => { + request_floodlight_criteria_report_properties_init(&mut request); + if request.floodlight_criteria.as_mut().unwrap().metric_names.is_none() { + request.floodlight_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.floodlight_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.pivoted" => { + request_cross_dimension_reach_criteria_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().pivoted = Some(arg_from_str(value.unwrap_or("false"), err, "cross-dimension-reach-criteria.pivoted", "boolean")); + }, + "cross-dimension-reach-criteria.date-range.start-date" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().start_date = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.date-range.kind" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.date-range.end-date" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().end_date = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.date-range.relative-date-range" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().date_range.as_mut().unwrap().relative_date_range = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.dimension" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + request.cross_dimension_reach_criteria.as_mut().unwrap().dimension = Some(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.overlap-metric-names" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + if request.cross_dimension_reach_criteria.as_mut().unwrap().overlap_metric_names.is_none() { + request.cross_dimension_reach_criteria.as_mut().unwrap().overlap_metric_names = Some(Default::default()); + } + request.cross_dimension_reach_criteria.as_mut().unwrap().overlap_metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "cross-dimension-reach-criteria.metric-names" => { + request_cross_dimension_reach_criteria_date_range_init(&mut request); + if request.cross_dimension_reach_criteria.as_mut().unwrap().metric_names.is_none() { + request.cross_dimension_reach_criteria.as_mut().unwrap().metric_names = Some(Default::default()); + } + request.cross_dimension_reach_criteria.as_mut().unwrap().metric_names.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active", "activities", "clicks-lookback-window", "criteria", "cross-dimension-reach-criteria", "custom-rich-media-events", "date-range", "delivery", "dimension", "dimension-name", "email-owner", "email-owner-delivery-type", "enable-all-dimension-combinations", "end-date", "etag", "every", "expiration-date", "file-name", "floodlight-config-id", "floodlight-criteria", "format", "id", "impressions-lookback-window", "include-attributed-ip-conversions", "include-unattributed-cookie-conversions", "include-unattributed-ip-conversions", "kind", "last-modified-time", "match-type", "maximum-click-interactions", "maximum-impression-interactions", "maximum-interaction-gap", "message", "metric-names", "name", "overlap-metric-names", "owner-profile-id", "path-to-conversion-criteria", "pivot-on-interaction-path", "pivoted", "reach-by-frequency-metric-names", "reach-criteria", "relative-date-range", "repeats", "repeats-on-week-days", "report-properties", "runs-on-day-of-month", "schedule", "start-date", "sub-account-id", "type", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.reports().update(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("report-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _sites_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.sites().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _sites_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Site::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_directory_site_id_dimension_value_init(request: &mut api::Site) { + if request.directory_site_id_dimension_value.is_none() { + request.directory_site_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Site) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_site_settings_creative_settings_init(request: &mut api::Site) { + request_site_settings_init(request); + if request.site_settings.as_mut().unwrap().creative_settings.is_none() { + request.site_settings.as_mut().unwrap().creative_settings = Some(Default::default()); + } + } + + fn request_site_settings_init(request: &mut api::Site) { + if request.site_settings.is_none() { + request.site_settings = Some(Default::default()); + } + } + + fn request_site_settings_lookback_configuration_init(request: &mut api::Site) { + request_site_settings_init(request); + if request.site_settings.as_mut().unwrap().lookback_configuration.is_none() { + request.site_settings.as_mut().unwrap().lookback_configuration = Some(Default::default()); + } + } + + fn request_site_settings_tag_setting_init(request: &mut api::Site) { + request_site_settings_init(request); + if request.site_settings.as_mut().unwrap().tag_setting.is_none() { + request.site_settings.as_mut().unwrap().tag_setting = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.kind" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.value" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.dimension-name" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.etag" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.match-type" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "site-settings.disable-brand-safe-ads" => { + request_site_settings_init(&mut request); + request.site_settings.as_mut().unwrap().disable_brand_safe_ads = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.disable-brand-safe-ads", "boolean")); + }, + "site-settings.active-view-opt-out" => { + request_site_settings_init(&mut request); + request.site_settings.as_mut().unwrap().active_view_opt_out = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.active-view-opt-out", "boolean")); + }, + "site-settings.lookback-configuration.click-duration" => { + request_site_settings_lookback_configuration_init(&mut request); + request.site_settings.as_mut().unwrap().lookback_configuration.as_mut().unwrap().click_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "site-settings.lookback-configuration.click-duration", "integer")); + }, + "site-settings.lookback-configuration.post-impression-activities-duration" => { + request_site_settings_lookback_configuration_init(&mut request); + request.site_settings.as_mut().unwrap().lookback_configuration.as_mut().unwrap().post_impression_activities_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "site-settings.lookback-configuration.post-impression-activities-duration", "integer")); + }, + "site-settings.disable-new-cookie" => { + request_site_settings_lookback_configuration_init(&mut request); + request.site_settings.as_mut().unwrap().disable_new_cookie = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.disable-new-cookie", "boolean")); + }, + "site-settings.tag-setting.include-click-through-urls" => { + request_site_settings_tag_setting_init(&mut request); + request.site_settings.as_mut().unwrap().tag_setting.as_mut().unwrap().include_click_through_urls = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.tag-setting.include-click-through-urls", "boolean")); + }, + "site-settings.tag-setting.include-click-tracking" => { + request_site_settings_tag_setting_init(&mut request); + request.site_settings.as_mut().unwrap().tag_setting.as_mut().unwrap().include_click_tracking = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.tag-setting.include-click-tracking", "boolean")); + }, + "site-settings.tag-setting.additional-key-values" => { + request_site_settings_tag_setting_init(&mut request); + request.site_settings.as_mut().unwrap().tag_setting.as_mut().unwrap().additional_key_values = Some(value.unwrap_or("").to_string()); + }, + "site-settings.tag-setting.keyword-option" => { + request_site_settings_tag_setting_init(&mut request); + request.site_settings.as_mut().unwrap().tag_setting.as_mut().unwrap().keyword_option = Some(value.unwrap_or("").to_string()); + }, + "site-settings.creative-settings.i-frame-header" => { + request_site_settings_creative_settings_init(&mut request); + request.site_settings.as_mut().unwrap().creative_settings.as_mut().unwrap().i_frame_header = Some(value.unwrap_or("").to_string()); + }, + "site-settings.creative-settings.i-frame-footer" => { + request_site_settings_creative_settings_init(&mut request); + request.site_settings.as_mut().unwrap().creative_settings.as_mut().unwrap().i_frame_footer = Some(value.unwrap_or("").to_string()); + }, + "approved" => { + request_site_settings_init(&mut request); + request.approved = Some(arg_from_str(value.unwrap_or("false"), err, "approved", "boolean")); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "key-name" => { + request_id_dimension_value_init(&mut request); + request.key_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id" => { + request_id_dimension_value_init(&mut request); + request.directory_site_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active-view-opt-out", "additional-key-values", "approved", "click-duration", "creative-settings", "dimension-name", "directory-site-id", "directory-site-id-dimension-value", "disable-brand-safe-ads", "disable-new-cookie", "etag", "i-frame-footer", "i-frame-header", "id", "id-dimension-value", "include-click-through-urls", "include-click-tracking", "key-name", "keyword-option", "kind", "lookback-configuration", "match-type", "name", "post-impression-activities-duration", "site-settings", "subaccount-id", "tag-setting", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.sites().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _sites_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.sites().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "unmapped-site" => { + call = call.unmapped_site(arg_from_str(value.unwrap_or("false"), err, "unmapped-site", "boolean")); + }, + "subaccount-id" => { + call = call.subaccount_id(value.unwrap_or("")); + }, + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "directory-site-ids" => { + call = call.add_directory_site_ids(value.unwrap_or("")); + }, + "campaign-ids" => { + call = call.add_campaign_ids(value.unwrap_or("")); + }, + "approved" => { + call = call.approved(arg_from_str(value.unwrap_or("false"), err, "approved", "boolean")); + }, + "ad-words-site" => { + call = call.ad_words_site(arg_from_str(value.unwrap_or("false"), err, "ad-words-site", "boolean")); + }, + "accepts-publisher-paid-placements" => { + call = call.accepts_publisher_paid_placements(arg_from_str(value.unwrap_or("false"), err, "accepts-publisher-paid-placements", "boolean")); + }, + "accepts-interstitial-placements" => { + call = call.accepts_interstitial_placements(arg_from_str(value.unwrap_or("false"), err, "accepts-interstitial-placements", "boolean")); + }, + "accepts-in-stream-video-placements" => { + call = call.accepts_in_stream_video_placements(arg_from_str(value.unwrap_or("false"), err, "accepts-in-stream-video-placements", "boolean")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["accepts-interstitial-placements", "accepts-publisher-paid-placements", "search-string", "subaccount-id", "directory-site-ids", "sort-field", "ids", "max-results", "page-token", "unmapped-site", "accepts-in-stream-video-placements", "ad-words-site", "campaign-ids", "approved", "sort-order"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _sites_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Site::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_directory_site_id_dimension_value_init(request: &mut api::Site) { + if request.directory_site_id_dimension_value.is_none() { + request.directory_site_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Site) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_site_settings_creative_settings_init(request: &mut api::Site) { + request_site_settings_init(request); + if request.site_settings.as_mut().unwrap().creative_settings.is_none() { + request.site_settings.as_mut().unwrap().creative_settings = Some(Default::default()); + } + } + + fn request_site_settings_init(request: &mut api::Site) { + if request.site_settings.is_none() { + request.site_settings = Some(Default::default()); + } + } + + fn request_site_settings_lookback_configuration_init(request: &mut api::Site) { + request_site_settings_init(request); + if request.site_settings.as_mut().unwrap().lookback_configuration.is_none() { + request.site_settings.as_mut().unwrap().lookback_configuration = Some(Default::default()); + } + } + + fn request_site_settings_tag_setting_init(request: &mut api::Site) { + request_site_settings_init(request); + if request.site_settings.as_mut().unwrap().tag_setting.is_none() { + request.site_settings.as_mut().unwrap().tag_setting = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.kind" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.value" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.dimension-name" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.etag" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.match-type" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "site-settings.disable-brand-safe-ads" => { + request_site_settings_init(&mut request); + request.site_settings.as_mut().unwrap().disable_brand_safe_ads = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.disable-brand-safe-ads", "boolean")); + }, + "site-settings.active-view-opt-out" => { + request_site_settings_init(&mut request); + request.site_settings.as_mut().unwrap().active_view_opt_out = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.active-view-opt-out", "boolean")); + }, + "site-settings.lookback-configuration.click-duration" => { + request_site_settings_lookback_configuration_init(&mut request); + request.site_settings.as_mut().unwrap().lookback_configuration.as_mut().unwrap().click_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "site-settings.lookback-configuration.click-duration", "integer")); + }, + "site-settings.lookback-configuration.post-impression-activities-duration" => { + request_site_settings_lookback_configuration_init(&mut request); + request.site_settings.as_mut().unwrap().lookback_configuration.as_mut().unwrap().post_impression_activities_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "site-settings.lookback-configuration.post-impression-activities-duration", "integer")); + }, + "site-settings.disable-new-cookie" => { + request_site_settings_lookback_configuration_init(&mut request); + request.site_settings.as_mut().unwrap().disable_new_cookie = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.disable-new-cookie", "boolean")); + }, + "site-settings.tag-setting.include-click-through-urls" => { + request_site_settings_tag_setting_init(&mut request); + request.site_settings.as_mut().unwrap().tag_setting.as_mut().unwrap().include_click_through_urls = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.tag-setting.include-click-through-urls", "boolean")); + }, + "site-settings.tag-setting.include-click-tracking" => { + request_site_settings_tag_setting_init(&mut request); + request.site_settings.as_mut().unwrap().tag_setting.as_mut().unwrap().include_click_tracking = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.tag-setting.include-click-tracking", "boolean")); + }, + "site-settings.tag-setting.additional-key-values" => { + request_site_settings_tag_setting_init(&mut request); + request.site_settings.as_mut().unwrap().tag_setting.as_mut().unwrap().additional_key_values = Some(value.unwrap_or("").to_string()); + }, + "site-settings.tag-setting.keyword-option" => { + request_site_settings_tag_setting_init(&mut request); + request.site_settings.as_mut().unwrap().tag_setting.as_mut().unwrap().keyword_option = Some(value.unwrap_or("").to_string()); + }, + "site-settings.creative-settings.i-frame-header" => { + request_site_settings_creative_settings_init(&mut request); + request.site_settings.as_mut().unwrap().creative_settings.as_mut().unwrap().i_frame_header = Some(value.unwrap_or("").to_string()); + }, + "site-settings.creative-settings.i-frame-footer" => { + request_site_settings_creative_settings_init(&mut request); + request.site_settings.as_mut().unwrap().creative_settings.as_mut().unwrap().i_frame_footer = Some(value.unwrap_or("").to_string()); + }, + "approved" => { + request_site_settings_init(&mut request); + request.approved = Some(arg_from_str(value.unwrap_or("false"), err, "approved", "boolean")); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "key-name" => { + request_id_dimension_value_init(&mut request); + request.key_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id" => { + request_id_dimension_value_init(&mut request); + request.directory_site_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active-view-opt-out", "additional-key-values", "approved", "click-duration", "creative-settings", "dimension-name", "directory-site-id", "directory-site-id-dimension-value", "disable-brand-safe-ads", "disable-new-cookie", "etag", "i-frame-footer", "i-frame-header", "id", "id-dimension-value", "include-click-through-urls", "include-click-tracking", "key-name", "keyword-option", "kind", "lookback-configuration", "match-type", "name", "post-impression-activities-duration", "site-settings", "subaccount-id", "tag-setting", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.sites().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _sites_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Site::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_directory_site_id_dimension_value_init(request: &mut api::Site) { + if request.directory_site_id_dimension_value.is_none() { + request.directory_site_id_dimension_value = Some(Default::default()); + } + } + + fn request_id_dimension_value_init(request: &mut api::Site) { + if request.id_dimension_value.is_none() { + request.id_dimension_value = Some(Default::default()); + } + } + + fn request_site_settings_creative_settings_init(request: &mut api::Site) { + request_site_settings_init(request); + if request.site_settings.as_mut().unwrap().creative_settings.is_none() { + request.site_settings.as_mut().unwrap().creative_settings = Some(Default::default()); + } + } + + fn request_site_settings_init(request: &mut api::Site) { + if request.site_settings.is_none() { + request.site_settings = Some(Default::default()); + } + } + + fn request_site_settings_lookback_configuration_init(request: &mut api::Site) { + request_site_settings_init(request); + if request.site_settings.as_mut().unwrap().lookback_configuration.is_none() { + request.site_settings.as_mut().unwrap().lookback_configuration = Some(Default::default()); + } + } + + fn request_site_settings_tag_setting_init(request: &mut api::Site) { + request_site_settings_init(request); + if request.site_settings.as_mut().unwrap().tag_setting.is_none() { + request.site_settings.as_mut().unwrap().tag_setting = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.kind" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.value" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.dimension-name" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.etag" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.match-type" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id-dimension-value.id" => { + request_directory_site_id_dimension_value_init(&mut request); + request.directory_site_id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "site-settings.disable-brand-safe-ads" => { + request_site_settings_init(&mut request); + request.site_settings.as_mut().unwrap().disable_brand_safe_ads = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.disable-brand-safe-ads", "boolean")); + }, + "site-settings.active-view-opt-out" => { + request_site_settings_init(&mut request); + request.site_settings.as_mut().unwrap().active_view_opt_out = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.active-view-opt-out", "boolean")); + }, + "site-settings.lookback-configuration.click-duration" => { + request_site_settings_lookback_configuration_init(&mut request); + request.site_settings.as_mut().unwrap().lookback_configuration.as_mut().unwrap().click_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "site-settings.lookback-configuration.click-duration", "integer")); + }, + "site-settings.lookback-configuration.post-impression-activities-duration" => { + request_site_settings_lookback_configuration_init(&mut request); + request.site_settings.as_mut().unwrap().lookback_configuration.as_mut().unwrap().post_impression_activities_duration = Some(arg_from_str(value.unwrap_or("-0"), err, "site-settings.lookback-configuration.post-impression-activities-duration", "integer")); + }, + "site-settings.disable-new-cookie" => { + request_site_settings_lookback_configuration_init(&mut request); + request.site_settings.as_mut().unwrap().disable_new_cookie = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.disable-new-cookie", "boolean")); + }, + "site-settings.tag-setting.include-click-through-urls" => { + request_site_settings_tag_setting_init(&mut request); + request.site_settings.as_mut().unwrap().tag_setting.as_mut().unwrap().include_click_through_urls = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.tag-setting.include-click-through-urls", "boolean")); + }, + "site-settings.tag-setting.include-click-tracking" => { + request_site_settings_tag_setting_init(&mut request); + request.site_settings.as_mut().unwrap().tag_setting.as_mut().unwrap().include_click_tracking = Some(arg_from_str(value.unwrap_or("false"), err, "site-settings.tag-setting.include-click-tracking", "boolean")); + }, + "site-settings.tag-setting.additional-key-values" => { + request_site_settings_tag_setting_init(&mut request); + request.site_settings.as_mut().unwrap().tag_setting.as_mut().unwrap().additional_key_values = Some(value.unwrap_or("").to_string()); + }, + "site-settings.tag-setting.keyword-option" => { + request_site_settings_tag_setting_init(&mut request); + request.site_settings.as_mut().unwrap().tag_setting.as_mut().unwrap().keyword_option = Some(value.unwrap_or("").to_string()); + }, + "site-settings.creative-settings.i-frame-header" => { + request_site_settings_creative_settings_init(&mut request); + request.site_settings.as_mut().unwrap().creative_settings.as_mut().unwrap().i_frame_header = Some(value.unwrap_or("").to_string()); + }, + "site-settings.creative-settings.i-frame-footer" => { + request_site_settings_creative_settings_init(&mut request); + request.site_settings.as_mut().unwrap().creative_settings.as_mut().unwrap().i_frame_footer = Some(value.unwrap_or("").to_string()); + }, + "approved" => { + request_site_settings_init(&mut request); + request.approved = Some(arg_from_str(value.unwrap_or("false"), err, "approved", "boolean")); + }, + "id-dimension-value.kind" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.value" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().value = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.dimension-name" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().dimension_name = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.etag" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().etag = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.match-type" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().match_type = Some(value.unwrap_or("").to_string()); + }, + "id-dimension-value.id" => { + request_id_dimension_value_init(&mut request); + request.id_dimension_value.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "key-name" => { + request_id_dimension_value_init(&mut request); + request.key_name = Some(value.unwrap_or("").to_string()); + }, + "directory-site-id" => { + request_id_dimension_value_init(&mut request); + request.directory_site_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_id_dimension_value_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request_id_dimension_value_init(&mut request); + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "active-view-opt-out", "additional-key-values", "approved", "click-duration", "creative-settings", "dimension-name", "directory-site-id", "directory-site-id-dimension-value", "disable-brand-safe-ads", "disable-new-cookie", "etag", "i-frame-footer", "i-frame-header", "id", "id-dimension-value", "include-click-through-urls", "include-click-tracking", "key-name", "keyword-option", "kind", "lookback-configuration", "match-type", "name", "post-impression-activities-duration", "site-settings", "subaccount-id", "tag-setting", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.sites().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _sizes_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.sizes().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _sizes_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Size::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "width" => { + request.width = Some(arg_from_str(value.unwrap_or("-0"), err, "width", "integer")); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "iab" => { + request.iab = Some(arg_from_str(value.unwrap_or("false"), err, "iab", "boolean")); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "height" => { + request.height = Some(arg_from_str(value.unwrap_or("-0"), err, "height", "integer")); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["height", "iab", "id", "kind", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.sizes().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _sizes_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.sizes().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "width" => { + call = call.width(arg_from_str(value.unwrap_or("-0"), err, "width", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "iab-standard" => { + call = call.iab_standard(arg_from_str(value.unwrap_or("false"), err, "iab-standard", "boolean")); + }, + "height" => { + call = call.height(arg_from_str(value.unwrap_or("-0"), err, "height", "integer")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["iab-standard", "width", "ids", "height"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _subaccounts_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.subaccounts().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _subaccounts_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Subaccount::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "available-permission-ids" => { + if request.available_permission_ids.is_none() { + request.available_permission_ids = Some(Default::default()); + } + request.available_permission_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "available-permission-ids", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.subaccounts().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _subaccounts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.subaccounts().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "sort-field", "ids", "max-results", "page-token", "sort-order"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _subaccounts_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Subaccount::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "available-permission-ids" => { + if request.available_permission_ids.is_none() { + request.available_permission_ids = Some(Default::default()); + } + request.available_permission_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "available-permission-ids", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.subaccounts().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _subaccounts_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::Subaccount::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "available-permission-ids" => { + if request.available_permission_ids.is_none() { + request.available_permission_ids = Some(Default::default()); + } + request.available_permission_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "available-permission-ids", "id", "kind", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.subaccounts().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _targetable_remarketing_lists_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.targetable_remarketing_lists().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _targetable_remarketing_lists_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.targetable_remarketing_lists().list(opt.value_of("profile-id").unwrap_or(""), opt.value_of("advertiser-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "name" => { + call = call.name(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "active" => { + call = call.active(arg_from_str(value.unwrap_or("false"), err, "active", "boolean")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["name", "sort-field", "max-results", "page-token", "sort-order", "active"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _user_profiles_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.user_profiles().get(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _user_profiles_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.user_profiles().list(); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _user_role_permission_groups_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.user_role_permission_groups().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _user_role_permission_groups_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.user_role_permission_groups().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _user_role_permissions_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.user_role_permissions().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _user_role_permissions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.user_role_permissions().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["ids"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _user_roles_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.user_roles().delete(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _user_roles_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.user_roles().get(opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _user_roles_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::UserRole::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "default-user-role" => { + request.default_user_role = Some(arg_from_str(value.unwrap_or("false"), err, "default-user-role", "boolean")); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "parent-user-role-id" => { + request.parent_user_role_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "default-user-role", "id", "kind", "name", "parent-user-role-id", "subaccount-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.user_roles().insert(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _user_roles_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.user_roles().list(opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "subaccount-id" => { + call = call.subaccount_id(value.unwrap_or("")); + }, + "sort-order" => { + call = call.sort_order(value.unwrap_or("")); + }, + "sort-field" => { + call = call.sort_field(value.unwrap_or("")); + }, + "search-string" => { + call = call.search_string(value.unwrap_or("")); + }, + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + "ids" => { + call = call.add_ids(value.unwrap_or("")); + }, + "account-user-role-only" => { + call = call.account_user_role_only(arg_from_str(value.unwrap_or("false"), err, "account-user-role-only", "boolean")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["search-string", "subaccount-id", "sort-field", "ids", "max-results", "page-token", "sort-order", "account-user-role-only"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _user_roles_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::UserRole::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "default-user-role" => { + request.default_user_role = Some(arg_from_str(value.unwrap_or("false"), err, "default-user-role", "boolean")); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "parent-user-role-id" => { + request.parent_user_role_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "default-user-role", "id", "kind", "name", "parent-user-role-id", "subaccount-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.user_roles().patch(request, opt.value_of("profile-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _user_roles_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::UserRole::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + match &temp_cursor.to_string()[..] { + "default-user-role" => { + request.default_user_role = Some(arg_from_str(value.unwrap_or("false"), err, "default-user-role", "boolean")); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "subaccount-id" => { + request.subaccount_id = Some(value.unwrap_or("").to_string()); + }, + "name" => { + request.name = Some(value.unwrap_or("").to_string()); + }, + "parent-user-role-id" => { + request.parent_user_role_id = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request.id = Some(value.unwrap_or("").to_string()); + }, + "account-id" => { + request.account_id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "default-user-role", "id", "kind", "name", "parent-user-role-id", "subaccount-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.user_roles().update(request, opt.value_of("profile-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { + let mut err = InvalidOptionsError::new(); + let mut call_result: Result<(), DoitError> = Ok(()); + let mut err_opt: Option<InvalidOptionsError> = None; + match self.opt.subcommand() { + ("account-active-ad-summaries", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._account_active_ad_summaries_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("account-active-ad-summaries".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("account-permission-groups", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._account_permission_groups_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._account_permission_groups_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("account-permission-groups".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("account-permissions", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._account_permissions_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._account_permissions_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("account-permissions".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("account-user-profiles", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._account_user_profiles_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._account_user_profiles_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._account_user_profiles_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._account_user_profiles_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._account_user_profiles_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("account-user-profiles".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("accounts", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._accounts_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._accounts_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._accounts_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._accounts_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("accounts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("ads", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._ads_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._ads_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._ads_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._ads_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._ads_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("ads".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("advertiser-groups", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._advertiser_groups_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._advertiser_groups_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._advertiser_groups_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._advertiser_groups_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._advertiser_groups_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._advertiser_groups_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("advertiser-groups".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("advertisers", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._advertisers_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._advertisers_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._advertisers_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._advertisers_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._advertisers_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("advertisers".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("browsers", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._browsers_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("browsers".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("campaign-creative-associations", Some(opt)) => { + match opt.subcommand() { + ("insert", Some(opt)) => { + call_result = self._campaign_creative_associations_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._campaign_creative_associations_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("campaign-creative-associations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("campaigns", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._campaigns_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._campaigns_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._campaigns_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._campaigns_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._campaigns_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("campaigns".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("change-logs", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._change_logs_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._change_logs_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("change-logs".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("cities", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._cities_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("cities".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("connection-types", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._connection_types_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._connection_types_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("connection-types".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("content-categories", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._content_categories_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._content_categories_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._content_categories_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._content_categories_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._content_categories_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._content_categories_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("content-categories".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("countries", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._countries_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._countries_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("countries".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("creative-assets", Some(opt)) => { + match opt.subcommand() { + ("insert", Some(opt)) => { + call_result = self._creative_assets_insert(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("creative-assets".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("creative-field-values", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._creative_field_values_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._creative_field_values_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._creative_field_values_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._creative_field_values_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._creative_field_values_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._creative_field_values_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("creative-field-values".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("creative-fields", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._creative_fields_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._creative_fields_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._creative_fields_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._creative_fields_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._creative_fields_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._creative_fields_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("creative-fields".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("creative-groups", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._creative_groups_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._creative_groups_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._creative_groups_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._creative_groups_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._creative_groups_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("creative-groups".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("creatives", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._creatives_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._creatives_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._creatives_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._creatives_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._creatives_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("creatives".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("dimension-values", Some(opt)) => { + match opt.subcommand() { + ("query", Some(opt)) => { + call_result = self._dimension_values_query(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("dimension-values".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("directory-site-contacts", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._directory_site_contacts_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._directory_site_contacts_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("directory-site-contacts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("directory-sites", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._directory_sites_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._directory_sites_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._directory_sites_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("directory-sites".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("event-tags", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._event_tags_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._event_tags_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._event_tags_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._event_tags_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._event_tags_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._event_tags_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("event-tags".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("files", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._files_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._files_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("files".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("floodlight-activities", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._floodlight_activities_delete(opt, dry_run, &mut err); + }, + ("generatetag", Some(opt)) => { + call_result = self._floodlight_activities_generatetag(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._floodlight_activities_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._floodlight_activities_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._floodlight_activities_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._floodlight_activities_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._floodlight_activities_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("floodlight-activities".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("floodlight-activity-groups", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._floodlight_activity_groups_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._floodlight_activity_groups_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._floodlight_activity_groups_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._floodlight_activity_groups_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._floodlight_activity_groups_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._floodlight_activity_groups_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("floodlight-activity-groups".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("floodlight-configurations", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._floodlight_configurations_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._floodlight_configurations_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._floodlight_configurations_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._floodlight_configurations_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("floodlight-configurations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("inventory-items", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._inventory_items_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._inventory_items_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("inventory-items".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("landing-pages", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._landing_pages_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._landing_pages_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._landing_pages_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._landing_pages_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._landing_pages_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._landing_pages_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("landing-pages".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("metros", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._metros_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("metros".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("mobile-carriers", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._mobile_carriers_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._mobile_carriers_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("mobile-carriers".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("operating-system-versions", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._operating_system_versions_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._operating_system_versions_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("operating-system-versions".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("operating-systems", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._operating_systems_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._operating_systems_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("operating-systems".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("order-documents", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._order_documents_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._order_documents_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("order-documents".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("orders", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._orders_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._orders_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("orders".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("placement-groups", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._placement_groups_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._placement_groups_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._placement_groups_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._placement_groups_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._placement_groups_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("placement-groups".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("placement-strategies", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._placement_strategies_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._placement_strategies_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._placement_strategies_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._placement_strategies_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._placement_strategies_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._placement_strategies_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("placement-strategies".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("placements", Some(opt)) => { + match opt.subcommand() { + ("generatetags", Some(opt)) => { + call_result = self._placements_generatetags(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._placements_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._placements_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._placements_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._placements_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._placements_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("placements".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("platform-types", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._platform_types_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._platform_types_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("platform-types".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("postal-codes", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._postal_codes_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._postal_codes_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("postal-codes".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("projects", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._projects_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._projects_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("projects".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("regions", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._regions_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("regions".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("remarketing-list-shares", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._remarketing_list_shares_get(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._remarketing_list_shares_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._remarketing_list_shares_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("remarketing-list-shares".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("remarketing-lists", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._remarketing_lists_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._remarketing_lists_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._remarketing_lists_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._remarketing_lists_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._remarketing_lists_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("remarketing-lists".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("reports", Some(opt)) => { + match opt.subcommand() { + ("compatible-fields-query", Some(opt)) => { + call_result = self._reports_compatible_fields_query(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._reports_delete(opt, dry_run, &mut err); + }, + ("files-get", Some(opt)) => { + call_result = self._reports_files_get(opt, dry_run, &mut err); + }, + ("files-list", Some(opt)) => { + call_result = self._reports_files_list(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._reports_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._reports_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._reports_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._reports_patch(opt, dry_run, &mut err); + }, + ("run", Some(opt)) => { + call_result = self._reports_run(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._reports_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("reports".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("sites", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._sites_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._sites_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._sites_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._sites_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._sites_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("sites".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("sizes", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._sizes_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._sizes_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._sizes_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("sizes".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("subaccounts", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._subaccounts_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._subaccounts_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._subaccounts_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._subaccounts_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._subaccounts_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("subaccounts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("targetable-remarketing-lists", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._targetable_remarketing_lists_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._targetable_remarketing_lists_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("targetable-remarketing-lists".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("user-profiles", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._user_profiles_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._user_profiles_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("user-profiles".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("user-role-permission-groups", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._user_role_permission_groups_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._user_role_permission_groups_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("user-role-permission-groups".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("user-role-permissions", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._user_role_permissions_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._user_role_permissions_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("user-role-permissions".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("user-roles", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._user_roles_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._user_roles_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._user_roles_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._user_roles_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._user_roles_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._user_roles_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("user-roles".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); + } + } + + if dry_run { + if err.issues.len() > 0 { + err_opt = Some(err); + } + Err(err_opt) + } else { + Ok(call_result) + } + } + + // Please note that this call will fail if any part of the opt can't be handled + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { + let (config_dir, secret) = { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { + Err(e) => return Err(InvalidOptionsError::single(e, 3)), + Ok(p) => p, + }; + + match cmn::application_secret_from_directory(&config_dir, "dfareporting2d1-secret.json", + "{\"installed\":{\"auth_uri\":\"https://accounts.google.com/o/oauth2/auth\",\"client_secret\":\"hCsslbCUyfehWMmbkG8vTYxG\",\"token_uri\":\"https://accounts.google.com/o/oauth2/token\",\"client_email\":\"\",\"redirect_uris\":[\"urn:ietf:wg:oauth:2.0:oob\",\"oob\"],\"client_x509_cert_url\":\"\",\"client_id\":\"620010449518-9ngf7o4dhs0dka470npqvor6dc5lqb9b.apps.googleusercontent.com\",\"auth_provider_x509_cert_url\":\"https://www.googleapis.com/oauth2/v1/certs\"}}") { + Ok(secret) => (config_dir, secret), + Err(e) => return Err(InvalidOptionsError::single(e, 4)) + } + }; + + let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, + if opt.is_present("debug-auth") { + hyper::Client::with_connector(mock::TeeConnector { + connector: hyper::net::HttpConnector(None) + }) + } else { + hyper::Client::new() + }, + JsonTokenStorage { + program_name: "dfareporting2d1", + db_dir: config_dir.clone(), + }, None); + + let client = + if opt.is_present("debug") { + hyper::Client::with_connector(mock::TeeConnector { + connector: hyper::net::HttpConnector(None) + }) + } else { + hyper::Client::new() + }; + let engine = Engine { + opt: opt, + hub: api::Dfareporting::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] + }; + + match engine._doit(true) { + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), + } + } + + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } + } +} + fn main() { - use cmn::UploadProtocol; + let upload_value_names = ["mode", "file"]; + let arg_data = [ + ("account-active-ad-summaries", "methods: 'get'", vec![ + ("get", + Some(r##"Gets the account's active ad summary by account ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/account-active-ad-summaries_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"summary-account-id"##), + None, + Some(r##"Account ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("account-permission-groups", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one account permission group by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/account-permission-groups_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Account permission group ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of account permission groups."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/account-permission-groups_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("account-permissions", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one account permission by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/account-permissions_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Account permission ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of account permissions."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/account-permissions_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("account-user-profiles", "methods: 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one account user profile by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/account-user-profiles_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"User profile ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new account user profile."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/account-user-profiles_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of account user profiles, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/account-user-profiles_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing account user profile. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/account-user-profiles_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"User profile ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing account user profile."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/account-user-profiles_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("accounts", "methods: 'get', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one account by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/accounts_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Account ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of accounts, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/accounts_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing account. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/accounts_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Account ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing account."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/accounts_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("ads", "methods: 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one ad by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/ads_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Ad ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new ad."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/ads_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of ads, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/ads_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing ad. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/ads_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Ad ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing ad."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/ads_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("advertiser-groups", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes an existing advertiser group."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/advertiser-groups_delete", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Advertiser group ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets one advertiser group by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/advertiser-groups_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Advertiser group ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new advertiser group."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/advertiser-groups_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of advertiser groups, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/advertiser-groups_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing advertiser group. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/advertiser-groups_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Advertiser group ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing advertiser group."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/advertiser-groups_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("advertisers", "methods: 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one advertiser by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/advertisers_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Advertiser ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new advertiser."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/advertisers_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of advertisers, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/advertisers_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing advertiser. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/advertisers_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Advertiser ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing advertiser."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/advertisers_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("browsers", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves a list of browsers."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/browsers_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("campaign-creative-associations", "methods: 'insert' and 'list'", vec![ + ("insert", + Some(r##"Associates a creative with the specified campaign. This method creates a default ad with dimensions matching the creative in the campaign if such a default ad does not exist already."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/campaign-creative-associations_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"campaign-id"##), + None, + Some(r##"Campaign ID in this association."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of creative IDs associated with the specified campaign."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/campaign-creative-associations_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"campaign-id"##), + None, + Some(r##"Campaign ID in this association."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("campaigns", "methods: 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one campaign by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/campaigns_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Campaign ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new campaign."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/campaigns_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"default-landing-page-name"##), + None, + Some(r##"Default landing page name for this new campaign. Must be less than 256 characters long."##), + Some(true), + Some(false)), + + (Some(r##"default-landing-page-url"##), + None, + Some(r##"Default landing page URL for this new campaign."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of campaigns, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/campaigns_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing campaign. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/campaigns_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Campaign ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing campaign."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/campaigns_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("change-logs", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one change log by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/change-logs_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Change log ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of change logs."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/change-logs_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("cities", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves a list of cities, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/cities_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("connection-types", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one connection type by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/connection-types_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Connection type ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of connection types."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/connection-types_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("content-categories", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes an existing content category."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/content-categories_delete", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Content category ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets one content category by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/content-categories_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Content category ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new content category."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/content-categories_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of content categories, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/content-categories_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing content category. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/content-categories_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Content category ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing content category."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/content-categories_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("countries", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one country by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/countries_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"dart-id"##), + None, + Some(r##"Country DART ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of countries."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/countries_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("creative-assets", "methods: 'insert'", vec![ + ("insert", + Some(r##"Inserts a new creative asset."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-assets_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"advertiser-id"##), + None, + Some(r##"Advertiser ID of this creative. This is a required field."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("creative-field-values", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes an existing creative field value."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-field-values_delete", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"creative-field-id"##), + None, + Some(r##"Creative field ID for this creative field value."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Creative Field Value ID"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets one creative field value by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-field-values_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"creative-field-id"##), + None, + Some(r##"Creative field ID for this creative field value."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Creative Field Value ID"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new creative field value."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-field-values_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"creative-field-id"##), + None, + Some(r##"Creative field ID for this creative field value."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of creative field values, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-field-values_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"creative-field-id"##), + None, + Some(r##"Creative field ID for this creative field value."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing creative field value. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-field-values_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"creative-field-id"##), + None, + Some(r##"Creative field ID for this creative field value."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Creative Field Value ID"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing creative field value."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-field-values_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"creative-field-id"##), + None, + Some(r##"Creative field ID for this creative field value."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("creative-fields", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes an existing creative field."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-fields_delete", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Creative Field ID"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets one creative field by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-fields_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Creative Field ID"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new creative field."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-fields_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of creative fields, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-fields_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing creative field. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-fields_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Creative Field ID"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing creative field."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-fields_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("creative-groups", "methods: 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one creative group by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-groups_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Creative group ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new creative group."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-groups_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of creative groups, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-groups_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing creative group. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-groups_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Creative group ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing creative group."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creative-groups_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("creatives", "methods: 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one creative by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creatives_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Creative ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new creative."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creatives_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of creatives, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creatives_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing creative. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creatives_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Creative ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing creative."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/creatives_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("dimension-values", "methods: 'query'", vec![ + ("query", + Some(r##"Retrieves list of report dimension values for a list of filters."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/dimension-values_query", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"The DFA user profile ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("directory-site-contacts", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one directory site contact by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/directory-site-contacts_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Directory site contact ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of directory site contacts, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/directory-site-contacts_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("directory-sites", "methods: 'get', 'insert' and 'list'", vec![ + ("get", + Some(r##"Gets one directory site by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/directory-sites_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Directory site ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new directory site."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/directory-sites_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of directory sites, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/directory-sites_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("event-tags", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes an existing event tag."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/event-tags_delete", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Event tag ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets one event tag by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/event-tags_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Event tag ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new event tag."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/event-tags_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of event tags, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/event-tags_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing event tag. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/event-tags_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Event tag ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing event tag."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/event-tags_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("files", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Retrieves a report file by its report ID and file ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/files_get", + vec![ + (Some(r##"report-id"##), + None, + Some(r##"The ID of the report."##), + Some(true), + Some(false)), + + (Some(r##"file-id"##), + None, + Some(r##"The ID of the report file."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists files for a user profile."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/files_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"The DFA profile ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("floodlight-activities", "methods: 'delete', 'generatetag', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes an existing floodlight activity."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-activities_delete", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Floodlight activity ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("generatetag", + Some(r##"Generates a tag for a floodlight activity."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-activities_generatetag", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Gets one floodlight activity by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-activities_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Floodlight activity ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new floodlight activity."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-activities_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of floodlight activities, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-activities_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing floodlight activity. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-activities_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Floodlight activity ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing floodlight activity."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-activities_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("floodlight-activity-groups", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes an existing floodlight activity group."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-activity-groups_delete", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Floodlight activity Group ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets one floodlight activity group by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-activity-groups_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Floodlight activity Group ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new floodlight activity group."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-activity-groups_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of floodlight activity groups, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-activity-groups_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing floodlight activity group. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-activity-groups_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Floodlight activity Group ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing floodlight activity group."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-activity-groups_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("floodlight-configurations", "methods: 'get', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one floodlight configuration by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-configurations_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Floodlight configuration ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of floodlight configurations, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-configurations_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing floodlight configuration. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-configurations_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Floodlight configuration ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing floodlight configuration."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/floodlight-configurations_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("inventory-items", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one inventory item by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/inventory-items_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"project-id"##), + None, + Some(r##"Project ID for order documents."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Inventory item ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of inventory items, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/inventory-items_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"project-id"##), + None, + Some(r##"Project ID for order documents."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("landing-pages", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes an existing campaign landing page."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/landing-pages_delete", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"campaign-id"##), + None, + Some(r##"Landing page campaign ID."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Landing page ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets one campaign landing page by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/landing-pages_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"campaign-id"##), + None, + Some(r##"Landing page campaign ID."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Landing page ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new landing page for the specified campaign."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/landing-pages_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"campaign-id"##), + None, + Some(r##"Landing page campaign ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of landing pages for the specified campaign."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/landing-pages_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"campaign-id"##), + None, + Some(r##"Landing page campaign ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing campaign landing page. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/landing-pages_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"campaign-id"##), + None, + Some(r##"Landing page campaign ID."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Landing page ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing campaign landing page."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/landing-pages_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"campaign-id"##), + None, + Some(r##"Landing page campaign ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("metros", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves a list of metros."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/metros_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("mobile-carriers", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one mobile carrier by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/mobile-carriers_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Mobile carrier ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of mobile carriers."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/mobile-carriers_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("operating-system-versions", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one operating system version by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/operating-system-versions_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Operating system version ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of operating system versions."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/operating-system-versions_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("operating-systems", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one operating system by DART ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/operating-systems_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"dart-id"##), + None, + Some(r##"Operating system DART ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of operating systems."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/operating-systems_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("order-documents", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one order document by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/order-documents_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"project-id"##), + None, + Some(r##"Project ID for order documents."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Order document ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of order documents, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/order-documents_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"project-id"##), + None, + Some(r##"Project ID for order documents."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("orders", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one order by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/orders_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"project-id"##), + None, + Some(r##"Project ID for orders."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Order ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of orders, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/orders_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"project-id"##), + None, + Some(r##"Project ID for orders."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("placement-groups", "methods: 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one placement group by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placement-groups_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Placement group ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new placement group."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placement-groups_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of placement groups, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placement-groups_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing placement group. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placement-groups_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Placement group ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing placement group."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placement-groups_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("placement-strategies", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes an existing placement strategy."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placement-strategies_delete", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Placement strategy ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets one placement strategy by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placement-strategies_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Placement strategy ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new placement strategy."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placement-strategies_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of placement strategies, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placement-strategies_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing placement strategy. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placement-strategies_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Placement strategy ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing placement strategy."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placement-strategies_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("placements", "methods: 'generatetags', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("generatetags", + Some(r##"Generates tags for a placement."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placements_generatetags", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Gets one placement by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placements_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Placement ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new placement."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placements_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of placements, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placements_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing placement. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placements_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Placement ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing placement."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/placements_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("platform-types", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one platform type by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/platform-types_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Platform type ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of platform types."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/platform-types_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("postal-codes", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one postal code by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/postal-codes_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"code"##), + None, + Some(r##"Postal code ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of postal codes."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/postal-codes_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("projects", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one project by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/projects_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Project ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of projects, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/projects_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("regions", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves a list of regions."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/regions_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("remarketing-list-shares", "methods: 'get', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one remarketing list share by remarketing list ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/remarketing-list-shares_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"remarketing-list-id"##), + None, + Some(r##"Remarketing list ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing remarketing list share. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/remarketing-list-shares_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"remarketing-list-id"##), + None, + Some(r##"Remarketing list ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing remarketing list share."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/remarketing-list-shares_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("remarketing-lists", "methods: 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one remarketing list by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/remarketing-lists_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Remarketing list ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new remarketing list."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/remarketing-lists_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of remarketing lists, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/remarketing-lists_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"advertiser-id"##), + None, + Some(r##"Select only remarketing lists owned by this advertiser."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing remarketing list. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/remarketing-lists_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Remarketing list ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing remarketing list."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/remarketing-lists_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("reports", "methods: 'compatible-fields-query', 'delete', 'files-get', 'files-list', 'get', 'insert', 'list', 'patch', 'run' and 'update'", vec![ + ("compatible-fields-query", + Some(r##"Returns the fields that are compatible to be selected in the respective sections of a report criteria, given the fields already selected in the input report and user permissions."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/reports_compatible-fields-query", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"The DFA user profile ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes a report by its ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/reports_delete", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"The DFA user profile ID."##), + Some(true), + Some(false)), + + (Some(r##"report-id"##), + None, + Some(r##"The ID of the report."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("files-get", + Some(r##"Retrieves a report file."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/reports_files-get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"The DFA profile ID."##), + Some(true), + Some(false)), + + (Some(r##"report-id"##), + None, + Some(r##"The ID of the report."##), + Some(true), + Some(false)), + + (Some(r##"file-id"##), + None, + Some(r##"The ID of the report file."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("files-list", + Some(r##"Lists files for a report."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/reports_files-list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"The DFA profile ID."##), + Some(true), + Some(false)), + + (Some(r##"report-id"##), + None, + Some(r##"The ID of the parent report."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Retrieves a report by its ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/reports_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"The DFA user profile ID."##), + Some(true), + Some(false)), + + (Some(r##"report-id"##), + None, + Some(r##"The ID of the report."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a report."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/reports_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"The DFA user profile ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves list of reports."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/reports_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"The DFA user profile ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a report. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/reports_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"The DFA user profile ID."##), + Some(true), + Some(false)), + + (Some(r##"report-id"##), + None, + Some(r##"The ID of the report."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("run", + Some(r##"Runs a report."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/reports_run", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"The DFA profile ID."##), + Some(true), + Some(false)), + + (Some(r##"report-id"##), + None, + Some(r##"The ID of the report."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a report."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/reports_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"The DFA user profile ID."##), + Some(true), + Some(false)), + + (Some(r##"report-id"##), + None, + Some(r##"The ID of the report."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("sites", "methods: 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one site by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/sites_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Site ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new site."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/sites_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of sites, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/sites_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing site. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/sites_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Site ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing site."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/sites_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("sizes", "methods: 'get', 'insert' and 'list'", vec![ + ("get", + Some(r##"Gets one size by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/sizes_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Size ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new size."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/sizes_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of sizes, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/sizes_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("subaccounts", "methods: 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one subaccount by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/subaccounts_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Subaccount ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new subaccount."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/subaccounts_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Gets a list of subaccounts, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/subaccounts_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing subaccount. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/subaccounts_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Subaccount ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing subaccount."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/subaccounts_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("targetable-remarketing-lists", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one remarketing list by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/targetable-remarketing-lists_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"Remarketing list ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of targetable remarketing lists, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/targetable-remarketing-lists_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"advertiser-id"##), + None, + Some(r##"Select only targetable remarketing lists targetable by these advertisers."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("user-profiles", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one user profile by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/user-profiles_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"The user profile ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves list of user profiles for a user."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/user-profiles_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("user-role-permission-groups", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one user role permission group by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/user-role-permission-groups_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"User role permission group ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Gets a list of all supported user role permission groups."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/user-role-permission-groups_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("user-role-permissions", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets one user role permission by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/user-role-permissions_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"User role permission ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Gets a list of user role permissions, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/user-role-permissions_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("user-roles", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes an existing user role."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/user-roles_delete", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"User role ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets one user role by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/user-roles_get", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"User role ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new user role."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/user-roles_insert", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of user roles, possibly filtered."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/user-roles_list", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing user role. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/user-roles_patch", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"User role ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing user role."##), + "Details at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli/user-roles_update", + vec![ + (Some(r##"profile-id"##), + None, + Some(r##"User profile ID associated with this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; let mut app = App::new("dfareporting2d1") .author("Sebastian Thiel <byronimo@gmail.com>") - .version("0.2.0") + .version("0.2.0+20150326") .about("Manage your DoubleClick Campaign Manager ad campaigns and reports.") .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_dfareporting2d1_cli") .arg(Arg::with_name("url") .long("scope") .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) .takes_value(true)) .arg(Arg::with_name("folder") .long("config-dir") - .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ${CONFIG_DIR}]") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) .takes_value(true)) .arg(Arg::with_name("debug") .long("debug") .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) .takes_value(false)) .arg(Arg::with_name("debug-auth") .long("debug-auth") .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) .takes_value(false)); - let arg_data = [ - ("account-active-ad-summaries", vec![ - ("get", Some("Gets the account's active ad summary by account ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("summary-account-id"), - None, - Some("Account ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("account-permission-groups", vec![ - ("get", Some("Gets one account permission group by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Account permission group ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves the list of account permission groups."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("account-permissions", vec![ - ("get", Some("Gets one account permission by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Account permission ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves the list of account permissions."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("account-user-profiles", vec![ - ("get", Some("Gets one account user profile by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("User profile ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new account user profile."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of account user profiles, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing account user profile. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("User profile ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing account user profile."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("accounts", vec![ - ("get", Some("Gets one account by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Account ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves the list of accounts, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing account. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Account ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing account."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("ads", vec![ - ("get", Some("Gets one ad by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Ad ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new ad."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of ads, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing ad. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Ad ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing ad."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("advertiser-groups", vec![ - ("delete", Some("Deletes an existing advertiser group."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Advertiser group ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - ]), - ("get", Some("Gets one advertiser group by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Advertiser group ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new advertiser group."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of advertiser groups, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing advertiser group. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Advertiser group ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing advertiser group."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("advertisers", vec![ - ("get", Some("Gets one advertiser by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Advertiser ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new advertiser."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of advertisers, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing advertiser. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Advertiser ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing advertiser."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("browsers", vec![ - ("list", Some("Retrieves a list of browsers."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("campaign-creative-associations", vec![ - ("insert", Some("Associates a creative with the specified campaign. This method creates a default ad with dimensions matching the creative in the campaign if such a default ad does not exist already."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("campaign-id"), - None, - Some("Campaign ID in this association."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves the list of creative IDs associated with the specified campaign."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("campaign-id"), - None, - Some("Campaign ID in this association."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("campaigns", vec![ - ("get", Some("Gets one campaign by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Campaign ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new campaign."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("default-landing-page-name"), - None, - Some("Default landing page name for this new campaign. Must be less than 256 characters long."), - Some(true), - Some(false), - None), - - (Some("default-landing-page-url"), - None, - Some("Default landing page URL for this new campaign."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of campaigns, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing campaign. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Campaign ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing campaign."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("change-logs", vec![ - ("get", Some("Gets one change log by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Change log ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of change logs."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("cities", vec![ - ("list", Some("Retrieves a list of cities, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("connection-types", vec![ - ("get", Some("Gets one connection type by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Connection type ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of connection types."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("content-categories", vec![ - ("delete", Some("Deletes an existing content category."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Content category ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - ]), - ("get", Some("Gets one content category by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Content category ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new content category."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of content categories, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing content category. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Content category ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing content category."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("countries", vec![ - ("get", Some("Gets one country by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("dart-id"), - None, - Some("Country DART ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of countries."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("creative-assets", vec![ - ("insert", Some("Inserts a new creative asset."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("advertiser-id"), - None, - Some("Advertiser ID of this creative. This is a required field."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("mode"), - Some("u"), - Some("Specify which file to upload"), - Some(false), - Some(false), - Some(vec!["simple","resumable"])), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("creative-field-values", vec![ - ("delete", Some("Deletes an existing creative field value."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("creative-field-id"), - None, - Some("Creative field ID for this creative field value."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Creative Field Value ID"), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - ]), - ("get", Some("Gets one creative field value by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("creative-field-id"), - None, - Some("Creative field ID for this creative field value."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Creative Field Value ID"), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new creative field value."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("creative-field-id"), - None, - Some("Creative field ID for this creative field value."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of creative field values, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("creative-field-id"), - None, - Some("Creative field ID for this creative field value."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing creative field value. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("creative-field-id"), - None, - Some("Creative field ID for this creative field value."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Creative Field Value ID"), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing creative field value."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("creative-field-id"), - None, - Some("Creative field ID for this creative field value."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("creative-fields", vec![ - ("delete", Some("Deletes an existing creative field."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Creative Field ID"), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - ]), - ("get", Some("Gets one creative field by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Creative Field ID"), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new creative field."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of creative fields, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing creative field. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Creative Field ID"), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing creative field."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("creative-groups", vec![ - ("get", Some("Gets one creative group by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Creative group ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new creative group."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of creative groups, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing creative group. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Creative group ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing creative group."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("creatives", vec![ - ("get", Some("Gets one creative by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Creative ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new creative."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of creatives, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing creative. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Creative ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing creative."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("dimension-values", vec![ - ("query", Some("Retrieves list of report dimension values for a list of filters."), - vec![ - (Some("profile-id"), - None, - Some("The DFA user profile ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("directory-site-contacts", vec![ - ("get", Some("Gets one directory site contact by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Directory site contact ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of directory site contacts, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("directory-sites", vec![ - ("get", Some("Gets one directory site by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Directory site ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new directory site."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of directory sites, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("event-tags", vec![ - ("delete", Some("Deletes an existing event tag."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Event tag ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - ]), - ("get", Some("Gets one event tag by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Event tag ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new event tag."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of event tags, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing event tag. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Event tag ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing event tag."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("files", vec![ - ("get", Some("Retrieves a report file by its report ID and file ID."), - vec![ - (Some("report-id"), - None, - Some("The ID of the report."), - Some(true), - Some(false), - None), - - (Some("file-id"), - None, - Some("The ID of the report file."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Lists files for a user profile."), - vec![ - (Some("profile-id"), - None, - Some("The DFA profile ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("floodlight-activities", vec![ - ("delete", Some("Deletes an existing floodlight activity."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Floodlight activity ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - ]), - ("generatetag", Some("Generates a tag for a floodlight activity."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("get", Some("Gets one floodlight activity by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Floodlight activity ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new floodlight activity."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of floodlight activities, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing floodlight activity. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Floodlight activity ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing floodlight activity."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("floodlight-activity-groups", vec![ - ("delete", Some("Deletes an existing floodlight activity group."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Floodlight activity Group ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - ]), - ("get", Some("Gets one floodlight activity group by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Floodlight activity Group ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new floodlight activity group."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of floodlight activity groups, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing floodlight activity group. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Floodlight activity Group ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing floodlight activity group."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("floodlight-configurations", vec![ - ("get", Some("Gets one floodlight configuration by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Floodlight configuration ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of floodlight configurations, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing floodlight configuration. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Floodlight configuration ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing floodlight configuration."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("inventory-items", vec![ - ("get", Some("Gets one inventory item by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("project-id"), - None, - Some("Project ID for order documents."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Inventory item ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of inventory items, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("project-id"), - None, - Some("Project ID for order documents."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("landing-pages", vec![ - ("delete", Some("Deletes an existing campaign landing page."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("campaign-id"), - None, - Some("Landing page campaign ID."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Landing page ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - ]), - ("get", Some("Gets one campaign landing page by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("campaign-id"), - None, - Some("Landing page campaign ID."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Landing page ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new landing page for the specified campaign."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("campaign-id"), - None, - Some("Landing page campaign ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves the list of landing pages for the specified campaign."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("campaign-id"), - None, - Some("Landing page campaign ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing campaign landing page. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("campaign-id"), - None, - Some("Landing page campaign ID."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Landing page ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing campaign landing page."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("campaign-id"), - None, - Some("Landing page campaign ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("metros", vec![ - ("list", Some("Retrieves a list of metros."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("mobile-carriers", vec![ - ("get", Some("Gets one mobile carrier by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Mobile carrier ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of mobile carriers."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("operating-system-versions", vec![ - ("get", Some("Gets one operating system version by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Operating system version ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of operating system versions."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("operating-systems", vec![ - ("get", Some("Gets one operating system by DART ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("dart-id"), - None, - Some("Operating system DART ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of operating systems."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("order-documents", vec![ - ("get", Some("Gets one order document by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("project-id"), - None, - Some("Project ID for order documents."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Order document ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of order documents, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("project-id"), - None, - Some("Project ID for order documents."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("orders", vec![ - ("get", Some("Gets one order by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("project-id"), - None, - Some("Project ID for orders."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Order ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of orders, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("project-id"), - None, - Some("Project ID for orders."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("placement-groups", vec![ - ("get", Some("Gets one placement group by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Placement group ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new placement group."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of placement groups, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing placement group. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Placement group ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing placement group."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("placement-strategies", vec![ - ("delete", Some("Deletes an existing placement strategy."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Placement strategy ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - ]), - ("get", Some("Gets one placement strategy by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Placement strategy ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new placement strategy."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of placement strategies, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing placement strategy. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Placement strategy ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing placement strategy."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("placements", vec![ - ("generatetags", Some("Generates tags for a placement."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("get", Some("Gets one placement by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Placement ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new placement."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of placements, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing placement. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Placement ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing placement."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("platform-types", vec![ - ("get", Some("Gets one platform type by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Platform type ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of platform types."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("postal-codes", vec![ - ("get", Some("Gets one postal code by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("code"), - None, - Some("Postal code ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of postal codes."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("projects", vec![ - ("get", Some("Gets one project by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Project ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of projects, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("regions", vec![ - ("list", Some("Retrieves a list of regions."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("remarketing-list-shares", vec![ - ("get", Some("Gets one remarketing list share by remarketing list ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("remarketing-list-id"), - None, - Some("Remarketing list ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing remarketing list share. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("remarketing-list-id"), - None, - Some("Remarketing list ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing remarketing list share."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("remarketing-lists", vec![ - ("get", Some("Gets one remarketing list by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Remarketing list ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new remarketing list."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of remarketing lists, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("advertiser-id"), - None, - Some("Select only remarketing lists owned by this advertiser."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing remarketing list. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Remarketing list ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing remarketing list."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("reports", vec![ - ("compatible-fields-query", Some("Returns the fields that are compatible to be selected in the respective sections of a report criteria, given the fields already selected in the input report and user permissions."), - vec![ - (Some("profile-id"), - None, - Some("The DFA user profile ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("delete", Some("Deletes a report by its ID."), - vec![ - (Some("profile-id"), - None, - Some("The DFA user profile ID."), - Some(true), - Some(false), - None), - - (Some("report-id"), - None, - Some("The ID of the report."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - ]), - ("files-get", Some("Retrieves a report file."), - vec![ - (Some("profile-id"), - None, - Some("The DFA profile ID."), - Some(true), - Some(false), - None), - - (Some("report-id"), - None, - Some("The ID of the report."), - Some(true), - Some(false), - None), - - (Some("file-id"), - None, - Some("The ID of the report file."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("files-list", Some("Lists files for a report."), - vec![ - (Some("profile-id"), - None, - Some("The DFA profile ID."), - Some(true), - Some(false), - None), - - (Some("report-id"), - None, - Some("The ID of the parent report."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("get", Some("Retrieves a report by its ID."), - vec![ - (Some("profile-id"), - None, - Some("The DFA user profile ID."), - Some(true), - Some(false), - None), - - (Some("report-id"), - None, - Some("The ID of the report."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Creates a report."), - vec![ - (Some("profile-id"), - None, - Some("The DFA user profile ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves list of reports."), - vec![ - (Some("profile-id"), - None, - Some("The DFA user profile ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates a report. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("The DFA user profile ID."), - Some(true), - Some(false), - None), - - (Some("report-id"), - None, - Some("The ID of the report."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("run", Some("Runs a report."), - vec![ - (Some("profile-id"), - None, - Some("The DFA profile ID."), - Some(true), - Some(false), - None), - - (Some("report-id"), - None, - Some("The ID of the report."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates a report."), - vec![ - (Some("profile-id"), - None, - Some("The DFA user profile ID."), - Some(true), - Some(false), - None), - - (Some("report-id"), - None, - Some("The ID of the report."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("sites", vec![ - ("get", Some("Gets one site by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Site ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new site."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of sites, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing site. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Site ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing site."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("sizes", vec![ - ("get", Some("Gets one size by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Size ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new size."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of sizes, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("subaccounts", vec![ - ("get", Some("Gets one subaccount by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Subaccount ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new subaccount."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Gets a list of subaccounts, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing subaccount. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Subaccount ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing subaccount."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("targetable-remarketing-lists", vec![ - ("get", Some("Gets one remarketing list by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("Remarketing list ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of targetable remarketing lists, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("advertiser-id"), - None, - Some("Select only targetable remarketing lists targetable by these advertisers."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("user-profiles", vec![ - ("get", Some("Gets one user profile by ID."), - vec![ - (Some("profile-id"), - None, - Some("The user profile ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves list of user profiles for a user."), - vec![ - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("user-role-permission-groups", vec![ - ("get", Some("Gets one user role permission group by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("User role permission group ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Gets a list of all supported user role permission groups."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("user-role-permissions", vec![ - ("get", Some("Gets one user role permission by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("User role permission ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Gets a list of user role permissions, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ("user-roles", vec![ - ("delete", Some("Deletes an existing user role."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("User role ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - ]), - ("get", Some("Gets one user role by ID."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("User role ID."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("insert", Some("Inserts a new user role."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("list", Some("Retrieves a list of user roles, possibly filtered."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("patch", Some("Updates an existing user role. This method supports patch semantics."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("id"), - None, - Some("User role ID."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ("update", Some("Updates an existing user role."), - vec![ - (Some("profile-id"), - None, - Some("User profile ID associated with this request."), - Some(true), - Some(false), - None), - - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), - Some(true), - Some(true), - None), - - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), - Some(false), - Some(true), - None), - - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), - Some(false), - Some(false), - None), - ]), - ]), - - ]; - for &(main_command_name, ref subcommands) in arg_data.iter() { - let mut mcmd = SubCommand::new(main_command_name); - for &(sub_command_name, ref desc, ref args) in subcommands { + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { let mut scmd = SubCommand::new(sub_command_name); if let &Some(desc) = desc { scmd = scmd.about(desc); } - for &(ref arg_name, ref flag, ref desc, ref required, ref multi, ref protocols) in args { - let mut arg = Arg::with_name(match (arg_name, flag) { - (&Some(an), _) => an, - (_, &Some(f)) => f, - _ => unreachable!(), - }); + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); if let &Some(short_flag) = flag { arg = arg.short(short_flag); } @@ -5938,18 +29983,13 @@ fn main() { if let &Some(multi) = multi { arg = arg.multiple(multi); } - if let &Some(ref protocols) = protocols { - arg = arg.possible_values(protocols.clone()); - arg = arg.requires("file"); - arg = arg.requires("mime"); + if arg_name_str == "mode" { + arg = arg.number_of_values(2); + arg = arg.value_names(&upload_value_names); - scmd = scmd.arg(Arg::with_name("file") - .short("f") - .required(false) - .help("The file to upload") - .takes_value(true)); scmd = scmd.arg(Arg::with_name("mime") .short("m") + .requires("mode") .required(false) .help("The file's mime time, like 'application/octet-stream'") .takes_value(true)); @@ -5960,7 +30000,31 @@ fn main() { } app = app.subcommand(mcmd); } - let matches = app.get_matches(); - + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { + Err(err) => { + env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); + }, + Ok(engine) => { + if let Err(doit_err) = engine.doit() { + env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } + } + } + } } \ No newline at end of file diff --git a/gen/dfareporting2d1/Cargo.toml b/gen/dfareporting2d1/Cargo.toml index 8dfebc568d..f59a869452 100644 --- a/gen/dfareporting2d1/Cargo.toml +++ b/gen/dfareporting2d1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-dfareporting2d1" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with dfareporting (protocol v2.1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/dfareporting2d1" @@ -15,9 +15,10 @@ keywords = ["dfareporting", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/dfareporting2d1/README.md b/gen/dfareporting2d1/README.md index 1f8051cf95..586b1b784c 100644 --- a/gen/dfareporting2d1/README.md +++ b/gen/dfareporting2d1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-dfareporting2d1` library allows access to all features of the *Google dfareporting* service. -This documentation was generated from *dfareporting* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *dfareporting:v2.1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *dfareporting* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *dfareporting:v2.1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *dfareporting* *v2d1* API can be found at the [official documentation site](https://developers.google.com/doubleclick-advertisers/reporting/). diff --git a/gen/dfareporting2d1/src/cmn.rs b/gen/dfareporting2d1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/dfareporting2d1/src/cmn.rs +++ b/gen/dfareporting2d1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/dfareporting2d1/src/lib.rs b/gen/dfareporting2d1/src/lib.rs index b3fe396914..e836c93130 100644 --- a/gen/dfareporting2d1/src/lib.rs +++ b/gen/dfareporting2d1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *dfareporting* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *dfareporting:v2.1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *dfareporting* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *dfareporting:v2.1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *dfareporting* *v2d1* API can be found at the //! [official documentation site](https://developers.google.com/doubleclick-advertisers/reporting/). @@ -298,7 +298,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -314,6 +313,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -439,7 +439,7 @@ impl<'a, C, A> Dfareporting<C, A> Dfareporting { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -610,7 +610,7 @@ impl<'a, C, A> Dfareporting<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -13236,7 +13236,7 @@ impl<'a, C, A> UserRolePermissionGroupGetCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13485,7 +13485,7 @@ impl<'a, C, A> UserRolePermissionGroupListCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13726,7 +13726,7 @@ impl<'a, C, A> PlatformTypeGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13975,7 +13975,7 @@ impl<'a, C, A> PlatformTypeListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14168,6 +14168,7 @@ impl<'a, C, A> CreativeFieldValuePatchCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CreativeFieldValue)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14225,11 +14226,20 @@ impl<'a, C, A> CreativeFieldValuePatchCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14505,7 +14515,7 @@ impl<'a, C, A> CreativeFieldValueGetCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14767,7 +14777,7 @@ impl<'a, C, A> CreativeFieldValueDeleteCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14969,6 +14979,7 @@ impl<'a, C, A> CreativeFieldValueInsertCall<'a, C, A> where C: BorrowMut<hyper:: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CreativeFieldValue)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15025,11 +15036,20 @@ impl<'a, C, A> CreativeFieldValueInsertCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15244,6 +15264,7 @@ impl<'a, C, A> CreativeFieldValueUpdateCall<'a, C, A> where C: BorrowMut<hyper:: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CreativeFieldValue)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15300,11 +15321,20 @@ impl<'a, C, A> CreativeFieldValueUpdateCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15602,7 +15632,7 @@ impl<'a, C, A> CreativeFieldValueListCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15846,6 +15876,7 @@ impl<'a, C, A> CreativeFieldUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CreativeField)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15901,11 +15932,20 @@ impl<'a, C, A> CreativeFieldUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -16200,7 +16240,7 @@ impl<'a, C, A> CreativeFieldListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16491,7 +16531,7 @@ impl<'a, C, A> CreativeFieldDeleteCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16732,7 +16772,7 @@ impl<'a, C, A> CreativeFieldGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16933,6 +16973,7 @@ impl<'a, C, A> CreativeFieldInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CreativeField)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -16988,11 +17029,20 @@ impl<'a, C, A> CreativeFieldInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17197,6 +17247,7 @@ impl<'a, C, A> CreativeFieldPatchCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CreativeField)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17253,11 +17304,20 @@ impl<'a, C, A> CreativeFieldPatchCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17471,6 +17531,7 @@ impl<'a, C, A> UserRoleInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, UserRole)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17526,11 +17587,20 @@ impl<'a, C, A> UserRoleInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17784,7 +17854,7 @@ impl<'a, C, A> UserRoleGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17985,6 +18055,7 @@ impl<'a, C, A> UserRoleUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, UserRole)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -18040,11 +18111,20 @@ impl<'a, C, A> UserRoleUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -18297,7 +18377,7 @@ impl<'a, C, A> UserRoleDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18489,6 +18569,7 @@ impl<'a, C, A> UserRolePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, UserRole)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -18545,11 +18626,20 @@ impl<'a, C, A> UserRolePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -18855,7 +18945,7 @@ impl<'a, C, A> UserRoleListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19153,7 +19243,7 @@ impl<'a, C, A> OperatingSystemVersionGetCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19402,7 +19492,7 @@ impl<'a, C, A> OperatingSystemVersionListCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19645,7 +19735,7 @@ impl<'a, C, A> LandingPageGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19857,6 +19947,7 @@ impl<'a, C, A> LandingPageUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client> /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LandingPage)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -19913,11 +20004,20 @@ impl<'a, C, A> LandingPageUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -20181,7 +20281,7 @@ impl<'a, C, A> LandingPageListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -20383,6 +20483,7 @@ impl<'a, C, A> LandingPageInsertCall<'a, C, A> where C: BorrowMut<hyper::Client> /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LandingPage)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -20439,11 +20540,20 @@ impl<'a, C, A> LandingPageInsertCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -20659,6 +20769,7 @@ impl<'a, C, A> LandingPagePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LandingPage)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -20716,11 +20827,20 @@ impl<'a, C, A> LandingPagePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -20995,7 +21115,7 @@ impl<'a, C, A> LandingPageDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -21199,6 +21319,7 @@ impl<'a, C, A> CreativeAssetInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, CreativeAssetMetadata)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -21263,11 +21384,20 @@ impl<'a, C, A> CreativeAssetInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -21372,7 +21502,7 @@ impl<'a, C, A> CreativeAssetInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -21400,6 +21530,7 @@ impl<'a, C, A> CreativeAssetInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -21588,6 +21719,7 @@ impl<'a, C, A> CampaignCreativeAssociationInsertCall<'a, C, A> where C: BorrowMu /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CampaignCreativeAssociation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -21644,11 +21776,20 @@ impl<'a, C, A> CampaignCreativeAssociationInsertCall<'a, C, A> where C: BorrowMu if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -21927,7 +22068,7 @@ impl<'a, C, A> CampaignCreativeAssociationListCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -22259,7 +22400,7 @@ impl<'a, C, A> ChangeLogListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -22573,7 +22714,7 @@ impl<'a, C, A> ChangeLogGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -22824,7 +22965,7 @@ impl<'a, C, A> RemarketingListShareGetCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -23026,6 +23167,7 @@ impl<'a, C, A> RemarketingListSharePatchCall<'a, C, A> where C: BorrowMut<hyper: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, RemarketingListShare)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -23082,11 +23224,20 @@ impl<'a, C, A> RemarketingListSharePatchCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -23300,6 +23451,7 @@ impl<'a, C, A> RemarketingListShareUpdateCall<'a, C, A> where C: BorrowMut<hyper /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, RemarketingListShare)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -23355,11 +23507,20 @@ impl<'a, C, A> RemarketingListShareUpdateCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -23618,7 +23779,7 @@ impl<'a, C, A> ReportRunCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -23827,6 +23988,7 @@ impl<'a, C, A> ReportPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Report)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -23883,11 +24045,20 @@ impl<'a, C, A> ReportPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -24171,7 +24342,7 @@ impl<'a, C, A> ReportFileListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -24400,6 +24571,7 @@ impl<'a, C, A> ReportInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Report)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -24455,11 +24627,20 @@ impl<'a, C, A> ReportInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -24664,6 +24845,7 @@ impl<'a, C, A> ReportUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Report)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -24720,11 +24902,20 @@ impl<'a, C, A> ReportUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -24938,6 +25129,7 @@ impl<'a, C, A> ReportCompatibleFieldQueryCall<'a, C, A> where C: BorrowMut<hyper /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CompatibleFields)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -24993,11 +25185,20 @@ impl<'a, C, A> ReportCompatibleFieldQueryCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -25251,7 +25452,7 @@ impl<'a, C, A> ReportGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -25525,7 +25726,7 @@ impl<'a, C, A> ReportFileGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -25785,7 +25986,7 @@ impl<'a, C, A> ReportDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -26049,7 +26250,7 @@ impl<'a, C, A> ReportListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -26275,6 +26476,7 @@ impl<'a, C, A> AdvertiserInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Advertiser)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -26330,11 +26532,20 @@ impl<'a, C, A> AdvertiserInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -26539,6 +26750,7 @@ impl<'a, C, A> AdvertiserPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Advertiser)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -26595,11 +26807,20 @@ impl<'a, C, A> AdvertiserPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -26933,7 +27154,7 @@ impl<'a, C, A> AdvertiserListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -27211,6 +27432,7 @@ impl<'a, C, A> AdvertiserUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Advertiser)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -27266,11 +27488,20 @@ impl<'a, C, A> AdvertiserUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -27524,7 +27755,7 @@ impl<'a, C, A> AdvertiserGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -27729,6 +27960,7 @@ impl<'a, C, A> DimensionValueQueryCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, DimensionValueList)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -27790,11 +28022,20 @@ impl<'a, C, A> DimensionValueQueryCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -28061,7 +28302,7 @@ impl<'a, C, A> FloodlightActivityGroupDeleteCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -28302,7 +28543,7 @@ impl<'a, C, A> FloodlightActivityGroupGetCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -28504,6 +28745,7 @@ impl<'a, C, A> FloodlightActivityGroupPatchCall<'a, C, A> where C: BorrowMut<hyp /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, FloodlightActivityGroup)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -28560,11 +28802,20 @@ impl<'a, C, A> FloodlightActivityGroupPatchCall<'a, C, A> where C: BorrowMut<hyp if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -28875,7 +29126,7 @@ impl<'a, C, A> FloodlightActivityGroupListCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -29130,6 +29381,7 @@ impl<'a, C, A> FloodlightActivityGroupInsertCall<'a, C, A> where C: BorrowMut<hy /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, FloodlightActivityGroup)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -29185,11 +29437,20 @@ impl<'a, C, A> FloodlightActivityGroupInsertCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -29393,6 +29654,7 @@ impl<'a, C, A> FloodlightActivityGroupUpdateCall<'a, C, A> where C: BorrowMut<hy /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, FloodlightActivityGroup)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -29448,11 +29710,20 @@ impl<'a, C, A> FloodlightActivityGroupUpdateCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -29704,7 +29975,7 @@ impl<'a, C, A> MetroListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -29988,7 +30259,7 @@ impl<'a, C, A> OrderListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -30292,7 +30563,7 @@ impl<'a, C, A> OrderGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -30553,7 +30824,7 @@ impl<'a, C, A> DirectorySiteContactGetCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -30845,7 +31116,7 @@ impl<'a, C, A> DirectorySiteContactListCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -31109,7 +31380,7 @@ impl<'a, C, A> UserProfileListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -31338,7 +31609,7 @@ impl<'a, C, A> UserProfileGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -31530,6 +31801,7 @@ impl<'a, C, A> AdPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Ad)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -31586,11 +31858,20 @@ impl<'a, C, A> AdPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -31804,6 +32085,7 @@ impl<'a, C, A> AdInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Ad)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -31859,11 +32141,20 @@ impl<'a, C, A> AdInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -32275,7 +32566,7 @@ impl<'a, C, A> AdListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth2 if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -32694,7 +32985,7 @@ impl<'a, C, A> AdGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth2: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -32895,6 +33186,7 @@ impl<'a, C, A> AdUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Ad)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -32950,11 +33242,20 @@ impl<'a, C, A> AdUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -33208,7 +33509,7 @@ impl<'a, C, A> AccountPermissionGetCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -33457,7 +33758,7 @@ impl<'a, C, A> AccountPermissionListCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -33696,7 +33997,7 @@ impl<'a, C, A> ConnectionTypeListCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -33937,7 +34238,7 @@ impl<'a, C, A> ConnectionTypeGetCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -34188,7 +34489,7 @@ impl<'a, C, A> AdvertiserGroupGetCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -34471,7 +34772,7 @@ impl<'a, C, A> AdvertiserGroupListCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -34705,6 +35006,7 @@ impl<'a, C, A> AdvertiserGroupInsertCall<'a, C, A> where C: BorrowMut<hyper::Cli /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AdvertiserGroup)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -34760,11 +35062,20 @@ impl<'a, C, A> AdvertiserGroupInsertCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -34968,6 +35279,7 @@ impl<'a, C, A> AdvertiserGroupUpdateCall<'a, C, A> where C: BorrowMut<hyper::Cli /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AdvertiserGroup)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -35023,11 +35335,20 @@ impl<'a, C, A> AdvertiserGroupUpdateCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -35232,6 +35553,7 @@ impl<'a, C, A> AdvertiserGroupPatchCall<'a, C, A> where C: BorrowMut<hyper::Clie /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AdvertiserGroup)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -35288,11 +35610,20 @@ impl<'a, C, A> AdvertiserGroupPatchCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -35555,7 +35886,7 @@ impl<'a, C, A> AdvertiserGroupDeleteCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -35746,6 +36077,7 @@ impl<'a, C, A> SiteInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Site)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -35801,11 +36133,20 @@ impl<'a, C, A> SiteInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -36059,7 +36400,7 @@ impl<'a, C, A> SiteGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -36395,7 +36736,7 @@ impl<'a, C, A> SiteListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -36694,6 +37035,7 @@ impl<'a, C, A> SiteUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Site)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -36749,11 +37091,20 @@ impl<'a, C, A> SiteUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -36958,6 +37309,7 @@ impl<'a, C, A> SitePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Site)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -37014,11 +37366,20 @@ impl<'a, C, A> SitePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -37282,7 +37643,7 @@ impl<'a, C, A> FloodlightActivityGetCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -37604,7 +37965,7 @@ impl<'a, C, A> FloodlightActivityListCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -37888,6 +38249,7 @@ impl<'a, C, A> FloodlightActivityInsertCall<'a, C, A> where C: BorrowMut<hyper:: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, FloodlightActivity)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -37943,11 +38305,20 @@ impl<'a, C, A> FloodlightActivityInsertCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -38200,7 +38571,7 @@ impl<'a, C, A> FloodlightActivityDeleteCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -38392,6 +38763,7 @@ impl<'a, C, A> FloodlightActivityPatchCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, FloodlightActivity)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -38448,11 +38820,20 @@ impl<'a, C, A> FloodlightActivityPatchCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -38719,7 +39100,7 @@ impl<'a, C, A> FloodlightActivityGeneratetagCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -38917,6 +39298,7 @@ impl<'a, C, A> FloodlightActivityUpdateCall<'a, C, A> where C: BorrowMut<hyper:: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, FloodlightActivity)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -38972,11 +39354,20 @@ impl<'a, C, A> FloodlightActivityUpdateCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -39228,7 +39619,7 @@ impl<'a, C, A> RegionListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -39419,6 +39810,7 @@ impl<'a, C, A> CreativeGroupInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CreativeGroup)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -39474,11 +39866,20 @@ impl<'a, C, A> CreativeGroupInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -39732,7 +40133,7 @@ impl<'a, C, A> CreativeGroupGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -39933,6 +40334,7 @@ impl<'a, C, A> CreativeGroupUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CreativeGroup)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -39988,11 +40390,20 @@ impl<'a, C, A> CreativeGroupUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -40292,7 +40703,7 @@ impl<'a, C, A> CreativeGroupListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -40542,6 +40953,7 @@ impl<'a, C, A> CreativeGroupPatchCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CreativeGroup)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -40598,11 +41010,20 @@ impl<'a, C, A> CreativeGroupPatchCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -40896,7 +41317,7 @@ impl<'a, C, A> TargetableRemarketingListListCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -41189,7 +41610,7 @@ impl<'a, C, A> TargetableRemarketingListGetCall<'a, C, A> where C: BorrowMut<hyp if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -41391,6 +41812,7 @@ impl<'a, C, A> SubaccountPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Subaccount)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -41447,11 +41869,20 @@ impl<'a, C, A> SubaccountPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -41665,6 +42096,7 @@ impl<'a, C, A> SubaccountInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Subaccount)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -41720,11 +42152,20 @@ impl<'a, C, A> SubaccountInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -42010,7 +42451,7 @@ impl<'a, C, A> SubaccountListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -42244,6 +42685,7 @@ impl<'a, C, A> SubaccountUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Subaccount)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -42299,11 +42741,20 @@ impl<'a, C, A> SubaccountUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -42557,7 +43008,7 @@ impl<'a, C, A> SubaccountGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -42808,7 +43259,7 @@ impl<'a, C, A> MobileCarrierGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -43057,7 +43508,7 @@ impl<'a, C, A> MobileCarrierListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -43298,7 +43749,7 @@ impl<'a, C, A> FloodlightConfigurationGetCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -43499,6 +43950,7 @@ impl<'a, C, A> FloodlightConfigurationUpdateCall<'a, C, A> where C: BorrowMut<hy /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, FloodlightConfiguration)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -43554,11 +44006,20 @@ impl<'a, C, A> FloodlightConfigurationUpdateCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -43763,6 +44224,7 @@ impl<'a, C, A> FloodlightConfigurationPatchCall<'a, C, A> where C: BorrowMut<hyp /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, FloodlightConfiguration)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -43819,11 +44281,20 @@ impl<'a, C, A> FloodlightConfigurationPatchCall<'a, C, A> where C: BorrowMut<hyp if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -44094,7 +44565,7 @@ impl<'a, C, A> FloodlightConfigurationListCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -44341,7 +44812,7 @@ impl<'a, C, A> OperatingSystemListCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -44582,7 +45053,7 @@ impl<'a, C, A> OperatingSystemGetCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -44856,7 +45327,7 @@ impl<'a, C, A> FileListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -45153,7 +45624,7 @@ impl<'a, C, A> FileGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -45509,7 +45980,7 @@ impl<'a, C, A> PlacementGroupListCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -45813,6 +46284,7 @@ impl<'a, C, A> PlacementGroupUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clie /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PlacementGroup)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -45868,11 +46340,20 @@ impl<'a, C, A> PlacementGroupUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -46076,6 +46557,7 @@ impl<'a, C, A> PlacementGroupInsertCall<'a, C, A> where C: BorrowMut<hyper::Clie /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PlacementGroup)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -46131,11 +46613,20 @@ impl<'a, C, A> PlacementGroupInsertCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -46389,7 +46880,7 @@ impl<'a, C, A> PlacementGroupGetCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -46591,6 +47082,7 @@ impl<'a, C, A> PlacementGroupPatchCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PlacementGroup)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -46647,11 +47139,20 @@ impl<'a, C, A> PlacementGroupPatchCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -46967,7 +47468,7 @@ impl<'a, C, A> InventoryItemListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -47279,7 +47780,7 @@ impl<'a, C, A> InventoryItemGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -47540,7 +48041,7 @@ impl<'a, C, A> UserRolePermissionGetCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -47798,7 +48299,7 @@ impl<'a, C, A> UserRolePermissionListCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -48045,7 +48546,7 @@ impl<'a, C, A> AccountPermissionGroupListCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -48286,7 +48787,7 @@ impl<'a, C, A> AccountPermissionGroupGetCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -48569,7 +49070,7 @@ impl<'a, C, A> ContentCategoryListCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -48803,6 +49304,7 @@ impl<'a, C, A> ContentCategoryUpdateCall<'a, C, A> where C: BorrowMut<hyper::Cli /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ContentCategory)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -48858,11 +49360,20 @@ impl<'a, C, A> ContentCategoryUpdateCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -49066,6 +49577,7 @@ impl<'a, C, A> ContentCategoryInsertCall<'a, C, A> where C: BorrowMut<hyper::Cli /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ContentCategory)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -49121,11 +49633,20 @@ impl<'a, C, A> ContentCategoryInsertCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -49378,7 +49899,7 @@ impl<'a, C, A> ContentCategoryDeleteCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -49619,7 +50140,7 @@ impl<'a, C, A> ContentCategoryGetCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -49821,6 +50342,7 @@ impl<'a, C, A> ContentCategoryPatchCall<'a, C, A> where C: BorrowMut<hyper::Clie /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ContentCategory)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -49877,11 +50399,20 @@ impl<'a, C, A> ContentCategoryPatchCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -50095,6 +50626,7 @@ impl<'a, C, A> CreativeUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Creative)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -50150,11 +50682,20 @@ impl<'a, C, A> CreativeUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -50358,6 +50899,7 @@ impl<'a, C, A> CreativeInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Creative)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -50413,11 +50955,20 @@ impl<'a, C, A> CreativeInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -50671,7 +51222,7 @@ impl<'a, C, A> CreativeGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -51024,7 +51575,7 @@ impl<'a, C, A> CreativeListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -51334,6 +51885,7 @@ impl<'a, C, A> CreativePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Creative)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -51390,11 +51942,20 @@ impl<'a, C, A> CreativePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -51658,7 +52219,7 @@ impl<'a, C, A> CampaignGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -51861,6 +52422,7 @@ impl<'a, C, A> CampaignInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Campaign)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -51918,11 +52480,20 @@ impl<'a, C, A> CampaignInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -52147,6 +52718,7 @@ impl<'a, C, A> CampaignPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Campaign)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -52203,11 +52775,20 @@ impl<'a, C, A> CampaignPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -52421,6 +53002,7 @@ impl<'a, C, A> CampaignUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Campaign)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -52476,11 +53058,20 @@ impl<'a, C, A> CampaignUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -52813,7 +53404,7 @@ impl<'a, C, A> CampaignListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -53148,7 +53739,7 @@ impl<'a, C, A> EventTagDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -53445,7 +54036,7 @@ impl<'a, C, A> EventTagListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -53708,6 +54299,7 @@ impl<'a, C, A> EventTagInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, EventTag)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -53763,11 +54355,20 @@ impl<'a, C, A> EventTagInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -53972,6 +54573,7 @@ impl<'a, C, A> EventTagPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, EventTag)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -54028,11 +54630,20 @@ impl<'a, C, A> EventTagPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -54246,6 +54857,7 @@ impl<'a, C, A> EventTagUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, EventTag)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -54301,11 +54913,20 @@ impl<'a, C, A> EventTagUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -54559,7 +55180,7 @@ impl<'a, C, A> EventTagGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -54810,7 +55431,7 @@ impl<'a, C, A> RemarketingListGetCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -55011,6 +55632,7 @@ impl<'a, C, A> RemarketingListUpdateCall<'a, C, A> where C: BorrowMut<hyper::Cli /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, RemarketingList)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -55066,11 +55688,20 @@ impl<'a, C, A> RemarketingListUpdateCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -55359,7 +55990,7 @@ impl<'a, C, A> RemarketingListListCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -55610,6 +56241,7 @@ impl<'a, C, A> RemarketingListPatchCall<'a, C, A> where C: BorrowMut<hyper::Clie /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, RemarketingList)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -55666,11 +56298,20 @@ impl<'a, C, A> RemarketingListPatchCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -55884,6 +56525,7 @@ impl<'a, C, A> RemarketingListInsertCall<'a, C, A> where C: BorrowMut<hyper::Cli /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, RemarketingList)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -55939,11 +56581,20 @@ impl<'a, C, A> RemarketingListInsertCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -56227,7 +56878,7 @@ impl<'a, C, A> CityListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -56449,6 +57100,7 @@ impl<'a, C, A> PlacementStrategyUpdateCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PlacementStrategy)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -56504,11 +57156,20 @@ impl<'a, C, A> PlacementStrategyUpdateCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -56762,7 +57423,7 @@ impl<'a, C, A> PlacementStrategyGetCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -57045,7 +57706,7 @@ impl<'a, C, A> PlacementStrategyListCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -57328,7 +57989,7 @@ impl<'a, C, A> PlacementStrategyDeleteCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -57519,6 +58180,7 @@ impl<'a, C, A> PlacementStrategyInsertCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PlacementStrategy)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -57574,11 +58236,20 @@ impl<'a, C, A> PlacementStrategyInsertCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -57783,6 +58454,7 @@ impl<'a, C, A> PlacementStrategyPatchCall<'a, C, A> where C: BorrowMut<hyper::Cl /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PlacementStrategy)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -57839,11 +58511,20 @@ impl<'a, C, A> PlacementStrategyPatchCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -58148,7 +58829,7 @@ impl<'a, C, A> ProjectListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -58440,7 +59121,7 @@ impl<'a, C, A> ProjectGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -58641,6 +59322,7 @@ impl<'a, C, A> DirectorySiteInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, DirectorySite)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -58696,11 +59378,20 @@ impl<'a, C, A> DirectorySiteInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -59021,7 +59712,7 @@ impl<'a, C, A> DirectorySiteListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -59354,7 +60045,7 @@ impl<'a, C, A> DirectorySiteGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -59555,6 +60246,7 @@ impl<'a, C, A> SizeInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Size)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -59610,11 +60302,20 @@ impl<'a, C, A> SizeInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -59890,7 +60591,7 @@ impl<'a, C, A> SizeListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -60160,7 +60861,7 @@ impl<'a, C, A> SizeGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -60411,7 +61112,7 @@ impl<'a, C, A> AccountActiveAdSummaryGetCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -60612,6 +61313,7 @@ impl<'a, C, A> AccountUserProfileUpdateCall<'a, C, A> where C: BorrowMut<hyper:: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AccountUserProfile)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -60667,11 +61369,20 @@ impl<'a, C, A> AccountUserProfileUpdateCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -60972,7 +61683,7 @@ impl<'a, C, A> AccountUserProfileListCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -61227,6 +61938,7 @@ impl<'a, C, A> AccountUserProfileInsertCall<'a, C, A> where C: BorrowMut<hyper:: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AccountUserProfile)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -61282,11 +61994,20 @@ impl<'a, C, A> AccountUserProfileInsertCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -61491,6 +62212,7 @@ impl<'a, C, A> AccountUserProfilePatchCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AccountUserProfile)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -61547,11 +62269,20 @@ impl<'a, C, A> AccountUserProfilePatchCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -61815,7 +62546,7 @@ impl<'a, C, A> AccountUserProfileGetCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -62064,7 +62795,7 @@ impl<'a, C, A> CountryListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -62305,7 +63036,7 @@ impl<'a, C, A> CountryGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -62558,7 +63289,7 @@ impl<'a, C, A> OrderDocumentGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -62876,7 +63607,7 @@ impl<'a, C, A> OrderDocumentListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -63193,7 +63924,7 @@ impl<'a, C, A> PostalCodeGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -63442,7 +64173,7 @@ impl<'a, C, A> PostalCodeListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -63681,7 +64412,7 @@ impl<'a, C, A> BrowserListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -63922,7 +64653,7 @@ impl<'a, C, A> AccountGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -64210,7 +64941,7 @@ impl<'a, C, A> AccountListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -64451,6 +65182,7 @@ impl<'a, C, A> AccountUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Account)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -64506,11 +65238,20 @@ impl<'a, C, A> AccountUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -64715,6 +65456,7 @@ impl<'a, C, A> AccountPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Account)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -64771,11 +65513,20 @@ impl<'a, C, A> AccountPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -64990,6 +65741,7 @@ impl<'a, C, A> PlacementPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Placement)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -65046,11 +65798,20 @@ impl<'a, C, A> PlacementPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -65446,7 +66207,7 @@ impl<'a, C, A> PlacementListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -65774,6 +66535,7 @@ impl<'a, C, A> PlacementInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Placement)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -65829,11 +66591,20 @@ impl<'a, C, A> PlacementInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -66037,6 +66808,7 @@ impl<'a, C, A> PlacementUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Placement)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -66092,11 +66864,20 @@ impl<'a, C, A> PlacementUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -66371,7 +67152,7 @@ impl<'a, C, A> PlacementGeneratetagCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -66635,7 +67416,7 @@ impl<'a, C, A> PlacementGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } diff --git a/gen/discovery1-cli/Cargo.toml b/gen/discovery1-cli/Cargo.toml index 5e1b2b0cf7..421b04bb8f 100644 --- a/gen/discovery1-cli/Cargo.toml +++ b/gen/discovery1-cli/Cargo.toml @@ -17,14 +17,14 @@ keywords = ["discovery", "google", "cli"] name = "discovery1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -clap = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-discovery1] path = "../discovery1" diff --git a/gen/discovery1-cli/README.md b/gen/discovery1-cli/README.md index f75cf04fd6..1dba9d527a 100644 --- a/gen/discovery1-cli/README.md +++ b/gen/discovery1-cli/README.md @@ -18,13 +18,12 @@ Everything else about the *discovery* API can be found at the This documentation was generated from the *discovery* API at revision *00000000*. The CLI is at version *0.2.0*. ```bash - discovery1 [options] apis get-rest <api> <version> [-p <v>...] [-o <out>] - discovery1 [options] apis list [-p <v>...] [-o <out>] +discovery1 [options] + apis + get-rest <api> <version> [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] discovery1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_discovery1_cli/index.html - Configuration: --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/discovery1-cli/src/cmn.rs b/gen/discovery1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/discovery1-cli/src/cmn.rs +++ b/gen/discovery1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/discovery1-cli/src/main.rs b/gen/discovery1-cli/src/main.rs index 9561bfce30..ce64a21fe3 100644 --- a/gen/discovery1-cli/src/main.rs +++ b/gen/discovery1-cli/src/main.rs @@ -4,88 +4,381 @@ #![feature(plugin, exit_status)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] +#[macro_use] extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_discovery1 as api; use std::env; use std::io::{self, Write}; use clap::{App, SubCommand, Arg}; +mod cmn; + +use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; + +use std::default::Default; +use std::str::FromStr; + +use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; +use serde::json; +use clap::ArgMatches; + +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, + hub: api::Discovery<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, +} + + +impl<'n, 'a> Engine<'n, 'a> { + fn _apis_get_rest(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.apis().get_rest(opt.value_of("api").unwrap_or(""), opt.value_of("version").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _apis_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.apis().list(); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "preferred" => { + call = call.preferred(arg_from_str(value.unwrap_or("false"), err, "preferred", "boolean")); + }, + "name" => { + call = call.name(value.unwrap_or("")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["name", "preferred"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { + let mut err = InvalidOptionsError::new(); + let mut call_result: Result<(), DoitError> = Ok(()); + let mut err_opt: Option<InvalidOptionsError> = None; + match self.opt.subcommand() { + ("apis", Some(opt)) => { + match opt.subcommand() { + ("get-rest", Some(opt)) => { + call_result = self._apis_get_rest(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._apis_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("apis".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); + } + } + + if dry_run { + if err.issues.len() > 0 { + err_opt = Some(err); + } + Err(err_opt) + } else { + Ok(call_result) + } + } + + // Please note that this call will fail if any part of the opt can't be handled + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { + let (config_dir, secret) = { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { + Err(e) => return Err(InvalidOptionsError::single(e, 3)), + Ok(p) => p, + }; + + match cmn::application_secret_from_directory(&config_dir, "discovery1-secret.json", + "{\"installed\":{\"auth_uri\":\"https://accounts.google.com/o/oauth2/auth\",\"client_secret\":\"hCsslbCUyfehWMmbkG8vTYxG\",\"token_uri\":\"https://accounts.google.com/o/oauth2/token\",\"client_email\":\"\",\"redirect_uris\":[\"urn:ietf:wg:oauth:2.0:oob\",\"oob\"],\"client_x509_cert_url\":\"\",\"client_id\":\"620010449518-9ngf7o4dhs0dka470npqvor6dc5lqb9b.apps.googleusercontent.com\",\"auth_provider_x509_cert_url\":\"https://www.googleapis.com/oauth2/v1/certs\"}}") { + Ok(secret) => (config_dir, secret), + Err(e) => return Err(InvalidOptionsError::single(e, 4)) + } + }; + + let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, + if opt.is_present("debug-auth") { + hyper::Client::with_connector(mock::TeeConnector { + connector: hyper::net::HttpConnector(None) + }) + } else { + hyper::Client::new() + }, + JsonTokenStorage { + program_name: "discovery1", + db_dir: config_dir.clone(), + }, None); + + let client = + if opt.is_present("debug") { + hyper::Client::with_connector(mock::TeeConnector { + connector: hyper::net::HttpConnector(None) + }) + } else { + hyper::Client::new() + }; + let engine = Engine { + opt: opt, + hub: api::Discovery::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] + }; + + match engine._doit(true) { + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), + } + } + + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } + } +} + fn main() { - let matches = - App::new("discovery1") + let arg_data = [ + ("apis", "methods: 'get-rest' and 'list'", vec![ + ("get-rest", + Some(r##"Retrieve the description of a particular version of an api."##), + "Details at http://byron.github.io/google-apis-rs/google_discovery1_cli/apis_get-rest", + vec![ + (Some(r##"api"##), + None, + Some(r##"The name of the API."##), + Some(true), + Some(false)), + + (Some(r##"version"##), + None, + Some(r##"The version of the API."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieve the list of APIs supported at this endpoint."##), + "Details at http://byron.github.io/google-apis-rs/google_discovery1_cli/apis_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("discovery1") .author("Sebastian Thiel <byronimo@gmail.com>") - .version("0.2.0") + .version("0.2.0+00000000") .about("Lets you discover information about other Google APIs, such as what APIs are available, the resource and method details for each API.") - .after_help("All documentation details can be found athttp://byron.github.io/google-apis-rs/google_discovery1_cli/index.html") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_discovery1_cli") .arg(Arg::with_name("folder") .long("config-dir") - .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ${CONFIG_DIR}]") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) .takes_value(true)) .arg(Arg::with_name("debug") .long("debug") .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) .takes_value(false)) .arg(Arg::with_name("debug-auth") .long("debug-auth") .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") - .takes_value(false)) - .subcommand( - SubCommand::new("apis") - .subcommand( - SubCommand::new("get-rest") - .about("Retrieve the description of a particular version of an api.") - .arg( - Arg::with_name("api") - .help("The name of the API.") - .required(true) - .multiple(false)) - .arg( - Arg::with_name("version") - .help("The version of the API.") - .required(true) - .multiple(false)) - .arg( - Arg::with_name("v") - .short("p") - .help("Set various fields of the request structure") - .takes_value(true) - .required(false) - .multiple(true)) - .arg( - Arg::with_name("<out>") - .short("o") - .help("Specify the file into which to write the programs output") - .takes_value(true) - .required(false) - .multiple(false)) - ) - .subcommand( - SubCommand::new("list") - .about("Retrieve the list of APIs supported at this endpoint.") - .arg( - Arg::with_name("v") - .short("p") - .help("Set various fields of the request structure") - .takes_value(true) - .required(false) - .multiple(true)) - .arg( - Arg::with_name("<out>") - .short("o") - .help("Specify the file into which to write the programs output") - .takes_value(true) - .required(false) - .multiple(false)) - ) - ) - .get_matches(); + .multiple(false) + .takes_value(false)); - + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { + Err(err) => { + env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); + }, + Ok(engine) => { + if let Err(doit_err) = engine.doit() { + env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } + } + } + } } \ No newline at end of file diff --git a/gen/discovery1/Cargo.toml b/gen/discovery1/Cargo.toml index 48b88f74db..250ccd2b04 100644 --- a/gen/discovery1/Cargo.toml +++ b/gen/discovery1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-discovery1" -version = "0.1.6+00000000" +version = "0.1.7+00000000" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with discovery (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/discovery1" @@ -15,9 +15,10 @@ keywords = ["discovery", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/discovery1/README.md b/gen/discovery1/README.md index 133844e10a..114c52baa8 100644 --- a/gen/discovery1/README.md +++ b/gen/discovery1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-discovery1` library allows access to all features of the *Google discovery* service. -This documentation was generated from *discovery* crate version *0.1.6+00000000*, where *00000000* is the exact revision of the *discovery:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *discovery* crate version *0.1.7+00000000*, where *00000000* is the exact revision of the *discovery:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *discovery* *v1* API can be found at the [official documentation site](https://developers.google.com/discovery/). diff --git a/gen/discovery1/src/cmn.rs b/gen/discovery1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/discovery1/src/cmn.rs +++ b/gen/discovery1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/discovery1/src/lib.rs b/gen/discovery1/src/lib.rs index 6cb3ac3306..72f0cb0da2 100644 --- a/gen/discovery1/src/lib.rs +++ b/gen/discovery1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *discovery* crate version *0.1.6+00000000*, where *00000000* is the exact revision of the *discovery:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *discovery* crate version *0.1.7+00000000*, where *00000000* is the exact revision of the *discovery:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *discovery* *v1* API can be found at the //! [official documentation site](https://developers.google.com/discovery/). @@ -167,7 +167,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -183,6 +182,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -277,7 +277,7 @@ impl<'a, C, A> Discovery<C, A> Discovery { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -286,7 +286,7 @@ impl<'a, C, A> Discovery<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -970,7 +970,7 @@ impl<'a, C, A> ApiGetRestCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1168,7 +1168,7 @@ impl<'a, C, A> ApiListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } diff --git a/gen/dns1-cli/Cargo.toml b/gen/dns1-cli/Cargo.toml index 9f56f057ce..8536b56c67 100644 --- a/gen/dns1-cli/Cargo.toml +++ b/gen/dns1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-dns1-cli" -version = "0.1.0+20150218" +version = "0.2.0+20150218" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with dns (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/dns1-cli" @@ -17,15 +17,14 @@ keywords = ["dns", "google", "cli"] name = "dns1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-dns1] path = "../dns1" diff --git a/gen/dns1-cli/README.md b/gen/dns1-cli/README.md index b743aab867..45a453f1bc 100644 --- a/gen/dns1-cli/README.md +++ b/gen/dns1-cli/README.md @@ -10,29 +10,34 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *dns* API can be found at the +[official documentation site](https://developers.google.com/cloud-dns). + # Usage -This documentation was generated from the *dns* API at revision *20150218*. The CLI is at version *0.1.0*. +This documentation was generated from the *dns* API at revision *20150218*. The CLI is at version *0.2.0*. ```bash - dns1 [options] changes create <project> <managed-zone> -r <kv>... [-p <v>...] [-o <out>] - dns1 [options] changes get <project> <managed-zone> <change-id> [-p <v>...] [-o <out>] - dns1 [options] changes list <project> <managed-zone> [-p <v>...] [-o <out>] - dns1 [options] managed-zones create <project> -r <kv>... [-p <v>...] [-o <out>] - dns1 [options] managed-zones delete <project> <managed-zone> [-p <v>...] - dns1 [options] managed-zones get <project> <managed-zone> [-p <v>...] [-o <out>] - dns1 [options] managed-zones list <project> [-p <v>...] [-o <out>] - dns1 [options] projects get <project> [-p <v>...] [-o <out>] - dns1 [options] resource-record-sets list <project> <managed-zone> [-p <v>...] [-o <out>] +dns1 [options] + changes + create <project> <managed-zone> (-r <kv>)... [-p <v>]... [-o <out>] + get <project> <managed-zone> <change-id> [-p <v>]... [-o <out>] + list <project> <managed-zone> [-p <v>]... [-o <out>] + managed-zones + create <project> (-r <kv>)... [-p <v>]... [-o <out>] + delete <project> <managed-zone> [-p <v>]... + get <project> <managed-zone> [-p <v>]... [-o <out>] + list <project> [-p <v>]... [-o <out>] + projects + get <project> [-p <v>]... [-o <out>] + resource-record-sets + list <project> <managed-zone> [-p <v>]... [-o <out>] dns1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_dns1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/dns1-cli/mkdocs.yml b/gen/dns1-cli/mkdocs.yml index 3acc121f45..0a61b47c9d 100644 --- a/gen/dns1-cli/mkdocs.yml +++ b/gen/dns1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: dns v0.1.0+20150218 +site_name: dns v0.2.0+20150218 site_url: http://byron.github.io/google-apis-rs/google-dns1-cli site_description: Write integrating applications with bcore diff --git a/gen/dns1-cli/src/cmn.rs b/gen/dns1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/dns1-cli/src/cmn.rs +++ b/gen/dns1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/dns1-cli/src/main.rs b/gen/dns1-cli/src/main.rs index 50875d0cb4..2c50fef1cb 100644 --- a/gen/dns1-cli/src/main.rs +++ b/gen/dns1-cli/src/main.rs @@ -2,77 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_dns1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - dns1 [options] changes create <project> <managed-zone> -r <kv>... [-p <v>...] [-o <out>] - dns1 [options] changes get <project> <managed-zone> <change-id> [-p <v>...] [-o <out>] - dns1 [options] changes list <project> <managed-zone> [-p <v>...] [-o <out>] - dns1 [options] managed-zones create <project> -r <kv>... [-p <v>...] [-o <out>] - dns1 [options] managed-zones delete <project> <managed-zone> [-p <v>...] - dns1 [options] managed-zones get <project> <managed-zone> [-p <v>...] [-o <out>] - dns1 [options] managed-zones list <project> [-p <v>...] [-o <out>] - dns1 [options] projects get <project> [-p <v>...] [-o <out>] - dns1 [options] resource-record-sets list <project> <managed-zone> [-p <v>...] [-o <out>] - dns1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_dns1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Dns<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _changes_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _changes_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Change::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -100,104 +78,113 @@ impl Engine { request.start_time = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "kind", "start-time", "status"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.changes().create(request, &self.opt.arg_project, &self.opt.arg_managed_zone); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.changes().create(request, opt.value_of("project").unwrap_or(""), opt.value_of("managed-zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _changes_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.changes().get(&self.opt.arg_project, &self.opt.arg_managed_zone, &self.opt.arg_change_id); - for parg in self.opt.arg_v.iter() { + fn _changes_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.changes().get(opt.value_of("project").unwrap_or(""), opt.value_of("managed-zone").unwrap_or(""), opt.value_of("change-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _changes_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.changes().list(&self.opt.arg_project, &self.opt.arg_managed_zone); - for parg in self.opt.arg_v.iter() { + fn _changes_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.changes().list(opt.value_of("project").unwrap_or(""), opt.value_of("managed-zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "sort-order" => { @@ -212,52 +199,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "sort-order", "max-results", "sort-by"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _managed_zones_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _managed_zones_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ManagedZone::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -300,148 +291,156 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-time", "description", "dns-name", "id", "kind", "name", "name-server-set", "name-servers"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.managed_zones().create(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.managed_zones().create(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _managed_zones_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.managed_zones().delete(&self.opt.arg_project, &self.opt.arg_managed_zone); - for parg in self.opt.arg_v.iter() { + fn _managed_zones_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.managed_zones().delete(opt.value_of("project").unwrap_or(""), opt.value_of("managed-zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _managed_zones_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.managed_zones().get(&self.opt.arg_project, &self.opt.arg_managed_zone); - for parg in self.opt.arg_v.iter() { + fn _managed_zones_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.managed_zones().get(opt.value_of("project").unwrap_or(""), opt.value_of("managed-zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _managed_zones_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.managed_zones().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _managed_zones_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.managed_zones().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -450,96 +449,104 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().get(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _projects_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().get(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _resource_record_sets_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.resource_record_sets().list(&self.opt.arg_project, &self.opt.arg_managed_zone); - for parg in self.opt.arg_v.iter() { + fn _resource_record_sets_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.resource_record_sets().list(opt.value_of("project").unwrap_or(""), opt.value_of("managed-zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "type" => { @@ -554,104 +561,134 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "type", "name", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_changes { - if self.opt.cmd_create { - call_result = self._changes_create(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._changes_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._changes_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("changes", Some(opt)) => { + match opt.subcommand() { + ("create", Some(opt)) => { + call_result = self._changes_create(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._changes_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._changes_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("changes".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("managed-zones", Some(opt)) => { + match opt.subcommand() { + ("create", Some(opt)) => { + call_result = self._managed_zones_create(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._managed_zones_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._managed_zones_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._managed_zones_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("managed-zones".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("projects", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._projects_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("projects".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("resource-record-sets", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._resource_record_sets_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("resource-record-sets".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_managed_zones { - if self.opt.cmd_create { - call_result = self._managed_zones_create(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._managed_zones_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._managed_zones_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._managed_zones_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_projects { - if self.opt.cmd_get { - call_result = self._projects_get(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_resource_record_sets { - if self.opt.cmd_list { - call_result = self._resource_record_sets_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -664,7 +701,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -677,7 +714,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -687,37 +724,381 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Dns::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("changes", "methods: 'create', 'get' and 'list'", vec![ + ("create", + Some(r##"Atomically update the ResourceRecordSet collection."##), + "Details at http://byron.github.io/google-apis-rs/google_dns1_cli/changes_create", + vec![ + (Some(r##"project"##), + None, + Some(r##"Identifies the project addressed by this request."##), + Some(true), + Some(false)), + + (Some(r##"managed-zone"##), + None, + Some(r##"Identifies the managed zone addressed by this request. Can be the managed zone name or id."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Fetch the representation of an existing Change."##), + "Details at http://byron.github.io/google-apis-rs/google_dns1_cli/changes_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Identifies the project addressed by this request."##), + Some(true), + Some(false)), + + (Some(r##"managed-zone"##), + None, + Some(r##"Identifies the managed zone addressed by this request. Can be the managed zone name or id."##), + Some(true), + Some(false)), + + (Some(r##"change-id"##), + None, + Some(r##"The identifier of the requested change, from a previous ResourceRecordSetsChangeResponse."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Enumerate Changes to a ResourceRecordSet collection."##), + "Details at http://byron.github.io/google-apis-rs/google_dns1_cli/changes_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Identifies the project addressed by this request."##), + Some(true), + Some(false)), + + (Some(r##"managed-zone"##), + None, + Some(r##"Identifies the managed zone addressed by this request. Can be the managed zone name or id."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("managed-zones", "methods: 'create', 'delete', 'get' and 'list'", vec![ + ("create", + Some(r##"Create a new ManagedZone."##), + "Details at http://byron.github.io/google-apis-rs/google_dns1_cli/managed-zones_create", + vec![ + (Some(r##"project"##), + None, + Some(r##"Identifies the project addressed by this request."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Delete a previously created ManagedZone."##), + "Details at http://byron.github.io/google-apis-rs/google_dns1_cli/managed-zones_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Identifies the project addressed by this request."##), + Some(true), + Some(false)), + + (Some(r##"managed-zone"##), + None, + Some(r##"Identifies the managed zone addressed by this request. Can be the managed zone name or id."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Fetch the representation of an existing ManagedZone."##), + "Details at http://byron.github.io/google-apis-rs/google_dns1_cli/managed-zones_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Identifies the project addressed by this request."##), + Some(true), + Some(false)), + + (Some(r##"managed-zone"##), + None, + Some(r##"Identifies the managed zone addressed by this request. Can be the managed zone name or id."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Enumerate ManagedZones that have been created but not yet deleted."##), + "Details at http://byron.github.io/google-apis-rs/google_dns1_cli/managed-zones_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Identifies the project addressed by this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("projects", "methods: 'get'", vec![ + ("get", + Some(r##"Fetch the representation of an existing Project."##), + "Details at http://byron.github.io/google-apis-rs/google_dns1_cli/projects_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Identifies the project addressed by this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("resource-record-sets", "methods: 'list'", vec![ + ("list", + Some(r##"Enumerate ResourceRecordSets that have been created but not yet deleted."##), + "Details at http://byron.github.io/google-apis-rs/google_dns1_cli/resource-record-sets_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Identifies the project addressed by this request."##), + Some(true), + Some(false)), + + (Some(r##"managed-zone"##), + None, + Some(r##"Identifies the managed zone addressed by this request. Can be the managed zone name or id."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("dns1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150218") + .about("The Google Cloud DNS API provides services for configuring and serving authoritative DNS records.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_dns1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/dns1/Cargo.toml b/gen/dns1/Cargo.toml index 003af1da95..b22ca1bcfe 100644 --- a/gen/dns1/Cargo.toml +++ b/gen/dns1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-dns1" -version = "0.1.6+20150218" +version = "0.1.7+20150218" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with dns (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/dns1" @@ -15,9 +15,10 @@ keywords = ["dns", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/dns1/README.md b/gen/dns1/README.md index 4324d3f3d4..59966656ef 100644 --- a/gen/dns1/README.md +++ b/gen/dns1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-dns1` library allows access to all features of the *Google dns* service. -This documentation was generated from *dns* crate version *0.1.6+20150218*, where *20150218* is the exact revision of the *dns:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *dns* crate version *0.1.7+20150218*, where *20150218* is the exact revision of the *dns:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *dns* *v1* API can be found at the [official documentation site](https://developers.google.com/cloud-dns). @@ -168,7 +168,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_dns1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_dns1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/dns1/src/cmn.rs b/gen/dns1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/dns1/src/cmn.rs +++ b/gen/dns1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/dns1/src/lib.rs b/gen/dns1/src/lib.rs index 16a604a6c4..a365556941 100644 --- a/gen/dns1/src/lib.rs +++ b/gen/dns1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *dns* crate version *0.1.6+20150218*, where *20150218* is the exact revision of the *dns:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *dns* crate version *0.1.7+20150218*, where *20150218* is the exact revision of the *dns:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *dns* *v1* API can be found at the //! [official documentation site](https://developers.google.com/cloud-dns). @@ -169,7 +169,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -178,7 +178,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -194,6 +193,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -320,7 +320,7 @@ impl<'a, C, A> Dns<C, A> Dns { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -338,7 +338,7 @@ impl<'a, C, A> Dns<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -996,6 +996,7 @@ impl<'a, C, A> ChangeCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Change)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1052,11 +1053,20 @@ impl<'a, C, A> ChangeCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1079,7 +1089,7 @@ impl<'a, C, A> ChangeCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1340,7 +1350,7 @@ impl<'a, C, A> ChangeListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1362,7 +1372,7 @@ impl<'a, C, A> ChangeListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1621,7 +1631,7 @@ impl<'a, C, A> ChangeGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1643,7 +1653,7 @@ impl<'a, C, A> ChangeGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1832,6 +1842,7 @@ impl<'a, C, A> ManagedZoneCreateCall<'a, C, A> where C: BorrowMut<hyper::Client> /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ManagedZone)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1887,11 +1898,20 @@ impl<'a, C, A> ManagedZoneCreateCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1914,7 +1934,7 @@ impl<'a, C, A> ManagedZoneCreateCall<'a, C, A> where C: BorrowMut<hyper::Client> request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2144,7 +2164,7 @@ impl<'a, C, A> ManagedZoneDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2166,7 +2186,7 @@ impl<'a, C, A> ManagedZoneDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2385,7 +2405,7 @@ impl<'a, C, A> ManagedZoneGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2407,7 +2427,7 @@ impl<'a, C, A> ManagedZoneGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2644,7 +2664,7 @@ impl<'a, C, A> ManagedZoneListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2666,7 +2686,7 @@ impl<'a, C, A> ManagedZoneListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2919,7 +2939,7 @@ impl<'a, C, A> ResourceRecordSetListCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2941,7 +2961,7 @@ impl<'a, C, A> ResourceRecordSetListCall<'a, C, A> where C: BorrowMut<hyper::Cli access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3196,7 +3216,7 @@ impl<'a, C, A> ProjectGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3218,7 +3238,7 @@ impl<'a, C, A> ProjectGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/doubleclickbidmanager1-cli/Cargo.toml b/gen/doubleclickbidmanager1-cli/Cargo.toml index 1e48003072..b6d5d6cc5d 100644 --- a/gen/doubleclickbidmanager1-cli/Cargo.toml +++ b/gen/doubleclickbidmanager1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-doubleclickbidmanager1-cli" -version = "0.1.0+20150326" +version = "0.2.0+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with DoubleClick Bid Manager (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/doubleclickbidmanager1-cli" @@ -17,15 +17,14 @@ keywords = ["doubleclickbidmanage", "google", "cli"] name = "doubleclickbidmanager1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-doubleclickbidmanager1] path = "../doubleclickbidmanager1" diff --git a/gen/doubleclickbidmanager1-cli/README.md b/gen/doubleclickbidmanager1-cli/README.md index bd1204a576..e046ac6755 100644 --- a/gen/doubleclickbidmanager1-cli/README.md +++ b/gen/doubleclickbidmanager1-cli/README.md @@ -10,24 +10,28 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *DoubleClick Bid Manager* API can be found at the +[official documentation site](https://developers.google.com/bid-manager/). + # Usage -This documentation was generated from the *DoubleClick Bid Manager* API at revision *20150326*. The CLI is at version *0.1.0*. +This documentation was generated from the *DoubleClick Bid Manager* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - doubleclickbidmanager1 [options] lineitems downloadlineitems -r <kv>... [-p <v>...] [-o <out>] - doubleclickbidmanager1 [options] lineitems uploadlineitems -r <kv>... [-p <v>...] [-o <out>] - doubleclickbidmanager1 [options] queries createquery -r <kv>... [-p <v>...] [-o <out>] - doubleclickbidmanager1 [options] queries deletequery <query-id> [-p <v>...] - doubleclickbidmanager1 [options] queries getquery <query-id> [-p <v>...] [-o <out>] - doubleclickbidmanager1 [options] queries listqueries [-p <v>...] [-o <out>] - doubleclickbidmanager1 [options] queries runquery <query-id> -r <kv>... [-p <v>...] - doubleclickbidmanager1 [options] reports listreports <query-id> [-p <v>...] [-o <out>] +doubleclickbidmanager1 [options] + lineitems + downloadlineitems (-r <kv>)... [-p <v>]... [-o <out>] + uploadlineitems (-r <kv>)... [-p <v>]... [-o <out>] + queries + createquery (-r <kv>)... [-p <v>]... [-o <out>] + deletequery <query-id> [-p <v>]... + getquery <query-id> [-p <v>]... [-o <out>] + listqueries [-p <v>]... [-o <out>] + runquery <query-id> (-r <kv>)... [-p <v>]... + reports + listreports <query-id> [-p <v>]... [-o <out>] doubleclickbidmanager1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_doubleclickbidmanager1_cli/index.html - Configuration: --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/doubleclickbidmanager1-cli/mkdocs.yml b/gen/doubleclickbidmanager1-cli/mkdocs.yml index 15eee9e5e6..ce1b3e2aa9 100644 --- a/gen/doubleclickbidmanager1-cli/mkdocs.yml +++ b/gen/doubleclickbidmanager1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: DoubleClick Bid Manager v0.1.0+20150326 +site_name: DoubleClick Bid Manager v0.2.0+20150326 site_url: http://byron.github.io/google-apis-rs/google-doubleclickbidmanager1-cli site_description: Write integrating applications with bcore diff --git a/gen/doubleclickbidmanager1-cli/src/cmn.rs b/gen/doubleclickbidmanager1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/doubleclickbidmanager1-cli/src/cmn.rs +++ b/gen/doubleclickbidmanager1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/doubleclickbidmanager1-cli/src/main.rs b/gen/doubleclickbidmanager1-cli/src/main.rs index e6d7946a10..c05917424d 100644 --- a/gen/doubleclickbidmanager1-cli/src/main.rs +++ b/gen/doubleclickbidmanager1-cli/src/main.rs @@ -2,72 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_doubleclickbidmanager1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - doubleclickbidmanager1 [options] lineitems downloadlineitems -r <kv>... [-p <v>...] [-o <out>] - doubleclickbidmanager1 [options] lineitems uploadlineitems -r <kv>... [-p <v>...] [-o <out>] - doubleclickbidmanager1 [options] queries createquery -r <kv>... [-p <v>...] [-o <out>] - doubleclickbidmanager1 [options] queries deletequery <query-id> [-p <v>...] - doubleclickbidmanager1 [options] queries getquery <query-id> [-p <v>...] [-o <out>] - doubleclickbidmanager1 [options] queries listqueries [-p <v>...] [-o <out>] - doubleclickbidmanager1 [options] queries runquery <query-id> -r <kv>... [-p <v>...] - doubleclickbidmanager1 [options] reports listreports <query-id> [-p <v>...] [-o <out>] - doubleclickbidmanager1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_doubleclickbidmanager1_cli/index.html - -Configuration: - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::DoubleClickBidManager<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _lineitems_downloadlineitems(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _lineitems_downloadlineitems(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::DownloadLineItemsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -95,57 +78,62 @@ impl Engine { request.format = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["filter-ids", "filter-type", "format"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.lineitems().downloadlineitems(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _lineitems_uploadlineitems(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _lineitems_uploadlineitems(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UploadLineItemsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -170,57 +158,62 @@ impl Engine { request.format = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["dry-run", "format", "line-items"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.lineitems().uploadlineitems(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _queries_createquery(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _queries_createquery(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Query::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -358,184 +351,196 @@ impl Engine { request.metadata.as_mut().unwrap().title = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["data-range", "end-time-ms", "format", "frequency", "google-cloud-storage-path-for-latest-report", "google-drive-path-for-latest-report", "group-bys", "include-invite-data", "kind", "latest-report-run-time-ms", "locale", "metadata", "metrics", "next-run-minute-of-day", "next-run-timezone-code", "params", "query-id", "report-count", "report-data-end-time-ms", "report-data-start-time-ms", "running", "schedule", "send-notification", "share-email-address", "timezone-code", "title", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.queries().createquery(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _queries_deletequery(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.queries().deletequery(&self.opt.arg_query_id); - for parg in self.opt.arg_v.iter() { + fn _queries_deletequery(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.queries().deletequery(opt.value_of("query-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _queries_getquery(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.queries().getquery(&self.opt.arg_query_id); - for parg in self.opt.arg_v.iter() { + fn _queries_getquery(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.queries().getquery(opt.value_of("query-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _queries_listqueries(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _queries_listqueries(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.queries().listqueries(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _queries_runquery(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _queries_runquery(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::RunQueryRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -563,143 +568,169 @@ impl Engine { request.data_range = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["data-range", "report-data-end-time-ms", "report-data-start-time-ms", "timezone-code"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.queries().runquery(request, &self.opt.arg_query_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.queries().runquery(request, opt.value_of("query-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _reports_listreports(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.reports().listreports(&self.opt.arg_query_id); - for parg in self.opt.arg_v.iter() { + fn _reports_listreports(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.reports().listreports(opt.value_of("query-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_lineitems { - if self.opt.cmd_downloadlineitems { - call_result = self._lineitems_downloadlineitems(dry_run, &mut err); - } else if self.opt.cmd_uploadlineitems { - call_result = self._lineitems_uploadlineitems(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("lineitems", Some(opt)) => { + match opt.subcommand() { + ("downloadlineitems", Some(opt)) => { + call_result = self._lineitems_downloadlineitems(opt, dry_run, &mut err); + }, + ("uploadlineitems", Some(opt)) => { + call_result = self._lineitems_uploadlineitems(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("lineitems".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("queries", Some(opt)) => { + match opt.subcommand() { + ("createquery", Some(opt)) => { + call_result = self._queries_createquery(opt, dry_run, &mut err); + }, + ("deletequery", Some(opt)) => { + call_result = self._queries_deletequery(opt, dry_run, &mut err); + }, + ("getquery", Some(opt)) => { + call_result = self._queries_getquery(opt, dry_run, &mut err); + }, + ("listqueries", Some(opt)) => { + call_result = self._queries_listqueries(opt, dry_run, &mut err); + }, + ("runquery", Some(opt)) => { + call_result = self._queries_runquery(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("queries".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("reports", Some(opt)) => { + match opt.subcommand() { + ("listreports", Some(opt)) => { + call_result = self._reports_listreports(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("reports".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_queries { - if self.opt.cmd_createquery { - call_result = self._queries_createquery(dry_run, &mut err); - } else if self.opt.cmd_deletequery { - call_result = self._queries_deletequery(dry_run, &mut err); - } else if self.opt.cmd_getquery { - call_result = self._queries_getquery(dry_run, &mut err); - } else if self.opt.cmd_listqueries { - call_result = self._queries_listqueries(dry_run, &mut err); - } else if self.opt.cmd_runquery { - call_result = self._queries_runquery(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_reports { - if self.opt.cmd_listreports { - call_result = self._reports_listreports(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -712,7 +743,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -725,7 +756,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -735,37 +766,291 @@ impl Engine { let engine = Engine { opt: opt, hub: api::DoubleClickBidManager::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("lineitems", "methods: 'downloadlineitems' and 'uploadlineitems'", vec![ + ("downloadlineitems", + Some(r##"Retrieves line items in CSV format."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclickbidmanager1_cli/lineitems_downloadlineitems", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("uploadlineitems", + Some(r##"Uploads line items in CSV format."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclickbidmanager1_cli/lineitems_uploadlineitems", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("queries", "methods: 'createquery', 'deletequery', 'getquery', 'listqueries' and 'runquery'", vec![ + ("createquery", + Some(r##"Creates a query."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclickbidmanager1_cli/queries_createquery", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("deletequery", + Some(r##"Deletes a stored query as well as the associated stored reports."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclickbidmanager1_cli/queries_deletequery", + vec![ + (Some(r##"query-id"##), + None, + Some(r##"Query ID to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("getquery", + Some(r##"Retrieves a stored query."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclickbidmanager1_cli/queries_getquery", + vec![ + (Some(r##"query-id"##), + None, + Some(r##"Query ID to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("listqueries", + Some(r##"Retrieves stored queries."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclickbidmanager1_cli/queries_listqueries", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("runquery", + Some(r##"Runs a stored query to generate a report."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclickbidmanager1_cli/queries_runquery", + vec![ + (Some(r##"query-id"##), + None, + Some(r##"Query ID to run."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("reports", "methods: 'listreports'", vec![ + ("listreports", + Some(r##"Retrieves stored reports."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclickbidmanager1_cli/reports_listreports", + vec![ + (Some(r##"query-id"##), + None, + Some(r##"Query ID with which the reports are associated."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("doubleclickbidmanager1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150326") + .about("API for viewing and managing your reports in DoubleClick Bid Manager.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_doubleclickbidmanager1_cli") + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/doubleclickbidmanager1/Cargo.toml b/gen/doubleclickbidmanager1/Cargo.toml index 546244700f..95b63e8568 100644 --- a/gen/doubleclickbidmanager1/Cargo.toml +++ b/gen/doubleclickbidmanager1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-doubleclickbidmanager1" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with DoubleClick Bid Manager (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/doubleclickbidmanager1" @@ -15,9 +15,10 @@ keywords = ["doubleclickbidmanage", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/doubleclickbidmanager1/README.md b/gen/doubleclickbidmanager1/README.md index b80e5d3b0a..dc3c6ec1c7 100644 --- a/gen/doubleclickbidmanager1/README.md +++ b/gen/doubleclickbidmanager1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-doubleclickbidmanager1` library allows access to all features of the *Google DoubleClick Bid Manager* service. -This documentation was generated from *DoubleClick Bid Manager* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *doubleclickbidmanager:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *DoubleClick Bid Manager* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *doubleclickbidmanager:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *DoubleClick Bid Manager* *v1* API can be found at the [official documentation site](https://developers.google.com/bid-manager/). @@ -162,7 +162,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_doubleclickbidmanager1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_doubleclickbidmanager1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/doubleclickbidmanager1/src/cmn.rs b/gen/doubleclickbidmanager1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/doubleclickbidmanager1/src/cmn.rs +++ b/gen/doubleclickbidmanager1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/doubleclickbidmanager1/src/lib.rs b/gen/doubleclickbidmanager1/src/lib.rs index c3437654cf..18ae350889 100644 --- a/gen/doubleclickbidmanager1/src/lib.rs +++ b/gen/doubleclickbidmanager1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *DoubleClick Bid Manager* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *doubleclickbidmanager:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *DoubleClick Bid Manager* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *doubleclickbidmanager:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *DoubleClick Bid Manager* *v1* API can be found at the //! [official documentation site](https://developers.google.com/bid-manager/). @@ -163,7 +163,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -172,7 +172,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -188,6 +187,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -282,7 +282,7 @@ impl<'a, C, A> DoubleClickBidManager<C, A> DoubleClickBidManager { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -297,7 +297,7 @@ impl<'a, C, A> DoubleClickBidManager<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1055,6 +1055,7 @@ impl<'a, C, A> LineitemUploadlineitemCall<'a, C, A> where C: BorrowMut<hyper::Cl /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, UploadLineItemsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1094,11 +1095,20 @@ impl<'a, C, A> LineitemUploadlineitemCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1107,7 +1117,7 @@ impl<'a, C, A> LineitemUploadlineitemCall<'a, C, A> where C: BorrowMut<hyper::Cl request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -1259,6 +1269,7 @@ impl<'a, C, A> LineitemDownloadlineitemCall<'a, C, A> where C: BorrowMut<hyper:: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, DownloadLineItemsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1298,11 +1309,20 @@ impl<'a, C, A> LineitemDownloadlineitemCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1311,7 +1331,7 @@ impl<'a, C, A> LineitemDownloadlineitemCall<'a, C, A> where C: BorrowMut<hyper:: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -1521,7 +1541,7 @@ impl<'a, C, A> ReportListreportCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1529,7 +1549,7 @@ impl<'a, C, A> ReportListreportCall<'a, C, A> where C: BorrowMut<hyper::Client>, loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -1711,7 +1731,7 @@ impl<'a, C, A> QueryListqueryCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1719,7 +1739,7 @@ impl<'a, C, A> QueryListqueryCall<'a, C, A> where C: BorrowMut<hyper::Client>, A loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -1917,7 +1937,7 @@ impl<'a, C, A> QueryGetqueryCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1925,7 +1945,7 @@ impl<'a, C, A> QueryGetqueryCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -2075,6 +2095,7 @@ impl<'a, C, A> QueryCreatequeryCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Query)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2114,11 +2135,20 @@ impl<'a, C, A> QueryCreatequeryCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2127,7 +2157,7 @@ impl<'a, C, A> QueryCreatequeryCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -2336,7 +2366,7 @@ impl<'a, C, A> QueryDeletequeryCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2344,7 +2374,7 @@ impl<'a, C, A> QueryDeletequeryCall<'a, C, A> where C: BorrowMut<hyper::Client>, loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -2485,6 +2515,7 @@ impl<'a, C, A> QueryRunqueryCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2548,11 +2579,20 @@ impl<'a, C, A> QueryRunqueryCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2561,7 +2601,7 @@ impl<'a, C, A> QueryRunqueryCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) diff --git a/gen/doubleclicksearch2-cli/Cargo.toml b/gen/doubleclicksearch2-cli/Cargo.toml index 7c4a12d671..22690666bf 100644 --- a/gen/doubleclicksearch2-cli/Cargo.toml +++ b/gen/doubleclicksearch2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-doubleclicksearch2-cli" -version = "0.1.0+20150303" +version = "0.2.0+20150303" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with doubleclicksearch (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/doubleclicksearch2-cli" @@ -17,15 +17,14 @@ keywords = ["doubleclicksearch", "google", "cli"] name = "doubleclicksearch2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-doubleclicksearch2] path = "../doubleclicksearch2" diff --git a/gen/doubleclicksearch2-cli/README.md b/gen/doubleclicksearch2-cli/README.md index f0e24ef6bf..c1a6b40e73 100644 --- a/gen/doubleclicksearch2-cli/README.md +++ b/gen/doubleclicksearch2-cli/README.md @@ -10,30 +10,34 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *doubleclicksearch* API can be found at the +[official documentation site](https://developers.google.com/doubleclick-search/). + # Usage -This documentation was generated from the *doubleclicksearch* API at revision *20150303*. The CLI is at version *0.1.0*. +This documentation was generated from the *doubleclicksearch* API at revision *20150303*. The CLI is at version *0.2.0*. ```bash - doubleclicksearch2 [options] conversion get <agency-id> <advertiser-id> <engine-account-id> <end-date> <row-count> <start-date> <start-row> [-p <v>...] [-o <out>] - doubleclicksearch2 [options] conversion insert -r <kv>... [-p <v>...] [-o <out>] - doubleclicksearch2 [options] conversion patch <advertiser-id> <agency-id> <end-date> <engine-account-id> <row-count> <start-date> <start-row> -r <kv>... [-p <v>...] [-o <out>] - doubleclicksearch2 [options] conversion update -r <kv>... [-p <v>...] [-o <out>] - doubleclicksearch2 [options] conversion update-availability -r <kv>... [-p <v>...] [-o <out>] - doubleclicksearch2 [options] reports generate -r <kv>... [-p <v>...] [-o <out>] - doubleclicksearch2 [options] reports get <report-id> [-p <v>...] [-o <out>] - doubleclicksearch2 [options] reports get-file <report-id> <report-fragment> [-p <v>...] [-o <out>] - doubleclicksearch2 [options] reports request -r <kv>... [-p <v>...] [-o <out>] - doubleclicksearch2 [options] saved-columns list <agency-id> <advertiser-id> [-p <v>...] [-o <out>] +doubleclicksearch2 [options] + conversion + get <agency-id> <advertiser-id> <engine-account-id> <end-date> <row-count> <start-date> <start-row> [-p <v>]... [-o <out>] + insert (-r <kv>)... [-p <v>]... [-o <out>] + patch <advertiser-id> <agency-id> <end-date> <engine-account-id> <row-count> <start-date> <start-row> (-r <kv>)... [-p <v>]... [-o <out>] + update (-r <kv>)... [-p <v>]... [-o <out>] + update-availability (-r <kv>)... [-p <v>]... [-o <out>] + reports + generate (-r <kv>)... [-p <v>]... [-o <out>] + get <report-id> [-p <v>]... [-o <out>] + get-file <report-id> <report-fragment> [-p <v>]... [-o <out>] + request (-r <kv>)... [-p <v>]... [-o <out>] + saved-columns + list <agency-id> <advertiser-id> [-p <v>]... [-o <out>] doubleclicksearch2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_doubleclicksearch2_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/doubleclicksearch2-cli/mkdocs.yml b/gen/doubleclicksearch2-cli/mkdocs.yml index 6c3c82aac1..a542a1a253 100644 --- a/gen/doubleclicksearch2-cli/mkdocs.yml +++ b/gen/doubleclicksearch2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: doubleclicksearch v0.1.0+20150303 +site_name: doubleclicksearch v0.2.0+20150303 site_url: http://byron.github.io/google-apis-rs/google-doubleclicksearch2-cli site_description: Write integrating applications with bcore diff --git a/gen/doubleclicksearch2-cli/src/cmn.rs b/gen/doubleclicksearch2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/doubleclicksearch2-cli/src/cmn.rs +++ b/gen/doubleclicksearch2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/doubleclicksearch2-cli/src/main.rs b/gen/doubleclicksearch2-cli/src/main.rs index b62982b009..22820421e4 100644 --- a/gen/doubleclicksearch2-cli/src/main.rs +++ b/gen/doubleclicksearch2-cli/src/main.rs @@ -2,80 +2,57 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_doubleclicksearch2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - doubleclicksearch2 [options] conversion get <agency-id> <advertiser-id> <engine-account-id> <end-date> <row-count> <start-date> <start-row> [-p <v>...] [-o <out>] - doubleclicksearch2 [options] conversion insert -r <kv>... [-p <v>...] [-o <out>] - doubleclicksearch2 [options] conversion patch <advertiser-id> <agency-id> <end-date> <engine-account-id> <row-count> <start-date> <start-row> -r <kv>... [-p <v>...] [-o <out>] - doubleclicksearch2 [options] conversion update -r <kv>... [-p <v>...] [-o <out>] - doubleclicksearch2 [options] conversion update-availability -r <kv>... [-p <v>...] [-o <out>] - doubleclicksearch2 [options] reports generate -r <kv>... [-p <v>...] [-o <out>] - doubleclicksearch2 [options] reports get <report-id> [-p <v>...] [-o <out>] - doubleclicksearch2 [options] reports get-file <report-id> <report-fragment> [-p <v>...] [-o <out>] - doubleclicksearch2 [options] reports request -r <kv>... [-p <v>...] [-o <out>] - doubleclicksearch2 [options] saved-columns list <agency-id> <advertiser-id> [-p <v>...] [-o <out>] - doubleclicksearch2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_doubleclicksearch2_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Doubleclicksearch<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _conversion_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let end_date: i32 = arg_from_str(&self.opt.arg_end_date, err, "<end-date>", "integer"); - let row_count: i32 = arg_from_str(&self.opt.arg_row_count, err, "<row-count>", "integer"); - let start_date: i32 = arg_from_str(&self.opt.arg_start_date, err, "<start-date>", "integer"); - let start_row: u32 = arg_from_str(&self.opt.arg_start_row, err, "<start-row>", "integer"); - let mut call = self.hub.conversion().get(&self.opt.arg_agency_id, &self.opt.arg_advertiser_id, &self.opt.arg_engine_account_id, end_date, row_count, start_date, start_row); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _conversion_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let end_date: i32 = arg_from_str(&opt.value_of("end-date").unwrap_or(""), err, "<end-date>", "integer"); + let row_count: i32 = arg_from_str(&opt.value_of("row-count").unwrap_or(""), err, "<row-count>", "integer"); + let start_date: i32 = arg_from_str(&opt.value_of("start-date").unwrap_or(""), err, "<start-date>", "integer"); + let start_row: u32 = arg_from_str(&opt.value_of("start-row").unwrap_or(""), err, "<start-row>", "integer"); + let mut call = self.hub.conversion().get(opt.value_of("agency-id").unwrap_or(""), opt.value_of("advertiser-id").unwrap_or(""), opt.value_of("engine-account-id").unwrap_or(""), end_date, row_count, start_date, start_row); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "criterion-id" => { @@ -90,52 +67,56 @@ impl Engine { "ad-group-id" => { call = call.ad_group_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["ad-group-id", "ad-id", "criterion-id", "campaign-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _conversion_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _conversion_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ConversionList::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -154,60 +135,65 @@ impl Engine { request.kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.conversion().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _conversion_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _conversion_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ConversionList::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -226,64 +212,69 @@ impl Engine { request.kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let end_date: i32 = arg_from_str(&self.opt.arg_end_date, err, "<end-date>", "integer"); - let row_count: i32 = arg_from_str(&self.opt.arg_row_count, err, "<row-count>", "integer"); - let start_date: i32 = arg_from_str(&self.opt.arg_start_date, err, "<start-date>", "integer"); - let start_row: u32 = arg_from_str(&self.opt.arg_start_row, err, "<start-row>", "integer"); - let mut call = self.hub.conversion().patch(request, &self.opt.arg_advertiser_id, &self.opt.arg_agency_id, end_date, &self.opt.arg_engine_account_id, row_count, start_date, start_row); - for parg in self.opt.arg_v.iter() { + let end_date: i32 = arg_from_str(&opt.value_of("end-date").unwrap_or(""), err, "<end-date>", "integer"); + let row_count: i32 = arg_from_str(&opt.value_of("row-count").unwrap_or(""), err, "<row-count>", "integer"); + let start_date: i32 = arg_from_str(&opt.value_of("start-date").unwrap_or(""), err, "<start-date>", "integer"); + let start_row: u32 = arg_from_str(&opt.value_of("start-row").unwrap_or(""), err, "<start-row>", "integer"); + let mut call = self.hub.conversion().patch(request, opt.value_of("advertiser-id").unwrap_or(""), opt.value_of("agency-id").unwrap_or(""), end_date, opt.value_of("engine-account-id").unwrap_or(""), row_count, start_date, start_row); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _conversion_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _conversion_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ConversionList::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -302,60 +293,65 @@ impl Engine { request.kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.conversion().update(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _conversion_update_availability(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _conversion_update_availability(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UpdateAvailabilityRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -371,60 +367,65 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.conversion().update_availability(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _reports_generate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _reports_generate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ReportRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -532,160 +533,171 @@ impl Engine { request.include_removed_entities = Some(arg_from_str(value.unwrap_or("false"), err, "include-removed-entities", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ad-group-id", "ad-id", "advertiser-id", "agency-id", "campaign-id", "changed-attributes-since-timestamp", "changed-metrics-since-timestamp", "download-format", "end-date", "engine-account-id", "include-deleted-entities", "include-removed-entities", "keyword-id", "max-rows-per-file", "report-scope", "report-type", "row-count", "start-date", "start-row", "statistics-currency", "time-range", "verify-single-time-zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.reports().generate(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _reports_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.reports().get(&self.opt.arg_report_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _reports_get_file(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let report_fragment: i32 = arg_from_str(&self.opt.arg_report_fragment, err, "<report-fragment>", "integer"); - let mut download_mode = false; - let mut call = self.hub.reports().get_file(&self.opt.arg_report_id, report_fragment); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _reports_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.reports().get(opt.value_of("report-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _reports_get_file(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let report_fragment: i32 = arg_from_str(&opt.value_of("report-fragment").unwrap_or(""), err, "<report-fragment>", "integer"); + let mut download_mode = false; + let mut call = self.hub.reports().get_file(opt.value_of("report-id").unwrap_or(""), report_fragment); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { if !download_mode { } else { io::copy(&mut response, &mut ostream).unwrap(); } - None + Ok(()) } } } } - fn _reports_request(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _reports_request(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ReportRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -793,155 +805,188 @@ impl Engine { request.include_removed_entities = Some(arg_from_str(value.unwrap_or("false"), err, "include-removed-entities", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ad-group-id", "ad-id", "advertiser-id", "agency-id", "campaign-id", "changed-attributes-since-timestamp", "changed-metrics-since-timestamp", "download-format", "end-date", "engine-account-id", "include-deleted-entities", "include-removed-entities", "keyword-id", "max-rows-per-file", "report-scope", "report-type", "row-count", "start-date", "start-row", "statistics-currency", "time-range", "verify-single-time-zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.reports().request(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _saved_columns_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.saved_columns().list(&self.opt.arg_agency_id, &self.opt.arg_advertiser_id); - for parg in self.opt.arg_v.iter() { + fn _saved_columns_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.saved_columns().list(opt.value_of("agency-id").unwrap_or(""), opt.value_of("advertiser-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_conversion { - if self.opt.cmd_get { - call_result = self._conversion_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._conversion_insert(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._conversion_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._conversion_update(dry_run, &mut err); - } else if self.opt.cmd_update_availability { - call_result = self._conversion_update_availability(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("conversion", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._conversion_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._conversion_insert(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._conversion_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._conversion_update(opt, dry_run, &mut err); + }, + ("update-availability", Some(opt)) => { + call_result = self._conversion_update_availability(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("conversion".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("reports", Some(opt)) => { + match opt.subcommand() { + ("generate", Some(opt)) => { + call_result = self._reports_generate(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._reports_get(opt, dry_run, &mut err); + }, + ("get-file", Some(opt)) => { + call_result = self._reports_get_file(opt, dry_run, &mut err); + }, + ("request", Some(opt)) => { + call_result = self._reports_request(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("reports".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("saved-columns", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._saved_columns_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("saved-columns".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_reports { - if self.opt.cmd_generate { - call_result = self._reports_generate(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._reports_get(dry_run, &mut err); - } else if self.opt.cmd_get_file { - call_result = self._reports_get_file(dry_run, &mut err); - } else if self.opt.cmd_request { - call_result = self._reports_request(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_saved_columns { - if self.opt.cmd_list { - call_result = self._saved_columns_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -954,7 +999,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -967,7 +1012,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -977,37 +1022,442 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Doubleclicksearch::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("conversion", "methods: 'get', 'insert', 'patch', 'update' and 'update-availability'", vec![ + ("get", + Some(r##"Retrieves a list of conversions from a DoubleClick Search engine account."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclicksearch2_cli/conversion_get", + vec![ + (Some(r##"agency-id"##), + None, + Some(r##"Numeric ID of the agency."##), + Some(true), + Some(false)), + + (Some(r##"advertiser-id"##), + None, + Some(r##"Numeric ID of the advertiser."##), + Some(true), + Some(false)), + + (Some(r##"engine-account-id"##), + None, + Some(r##"Numeric ID of the engine account."##), + Some(true), + Some(false)), + + (Some(r##"end-date"##), + None, + Some(r##"Last date (inclusive) on which to retrieve conversions. Format is yyyymmdd."##), + Some(true), + Some(false)), + + (Some(r##"row-count"##), + None, + Some(r##"The number of conversions to return per call."##), + Some(true), + Some(false)), + + (Some(r##"start-date"##), + None, + Some(r##"First date (inclusive) on which to retrieve conversions. Format is yyyymmdd."##), + Some(true), + Some(false)), + + (Some(r##"start-row"##), + None, + Some(r##"The 0-based starting index for retrieving conversions results."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a batch of new conversions into DoubleClick Search."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclicksearch2_cli/conversion_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a batch of conversions in DoubleClick Search. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclicksearch2_cli/conversion_patch", + vec![ + (Some(r##"advertiser-id"##), + None, + Some(r##"Numeric ID of the advertiser."##), + Some(true), + Some(false)), + + (Some(r##"agency-id"##), + None, + Some(r##"Numeric ID of the agency."##), + Some(true), + Some(false)), + + (Some(r##"end-date"##), + None, + Some(r##"Last date (inclusive) on which to retrieve conversions. Format is yyyymmdd."##), + Some(true), + Some(false)), + + (Some(r##"engine-account-id"##), + None, + Some(r##"Numeric ID of the engine account."##), + Some(true), + Some(false)), + + (Some(r##"row-count"##), + None, + Some(r##"The number of conversions to return per call."##), + Some(true), + Some(false)), + + (Some(r##"start-date"##), + None, + Some(r##"First date (inclusive) on which to retrieve conversions. Format is yyyymmdd."##), + Some(true), + Some(false)), + + (Some(r##"start-row"##), + None, + Some(r##"The 0-based starting index for retrieving conversions results."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a batch of conversions in DoubleClick Search."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclicksearch2_cli/conversion_update", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update-availability", + Some(r##"Updates the availabilities of a batch of floodlight activities in DoubleClick Search."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclicksearch2_cli/conversion_update-availability", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("reports", "methods: 'generate', 'get', 'get-file' and 'request'", vec![ + ("generate", + Some(r##"Generates and returns a report immediately."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclicksearch2_cli/reports_generate", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Polls for the status of a report request."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclicksearch2_cli/reports_get", + vec![ + (Some(r##"report-id"##), + None, + Some(r##"ID of the report request being polled."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-file", + Some(r##"Downloads a report file encoded in UTF-8."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclicksearch2_cli/reports_get-file", + vec![ + (Some(r##"report-id"##), + None, + Some(r##"ID of the report."##), + Some(true), + Some(false)), + + (Some(r##"report-fragment"##), + None, + Some(r##"The index of the report fragment to download."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("request", + Some(r##"Inserts a report request into the reporting system."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclicksearch2_cli/reports_request", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("saved-columns", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieve the list of saved columns for a specified advertiser."##), + "Details at http://byron.github.io/google-apis-rs/google_doubleclicksearch2_cli/saved-columns_list", + vec![ + (Some(r##"agency-id"##), + None, + Some(r##"DS ID of the agency."##), + Some(true), + Some(false)), + + (Some(r##"advertiser-id"##), + None, + Some(r##"DS ID of the advertiser."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("doubleclicksearch2") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150303") + .about("Report and modify your advertising data in DoubleClick Search (for example, campaigns, ad groups, keywords, and conversions).") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_doubleclicksearch2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/doubleclicksearch2/Cargo.toml b/gen/doubleclicksearch2/Cargo.toml index ecf9b7695f..0c61c8a524 100644 --- a/gen/doubleclicksearch2/Cargo.toml +++ b/gen/doubleclicksearch2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-doubleclicksearch2" -version = "0.1.6+20150303" +version = "0.1.7+20150303" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with doubleclicksearch (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/doubleclicksearch2" @@ -15,9 +15,10 @@ keywords = ["doubleclicksearch", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/doubleclicksearch2/README.md b/gen/doubleclicksearch2/README.md index a42321bd28..1902938c7c 100644 --- a/gen/doubleclicksearch2/README.md +++ b/gen/doubleclicksearch2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-doubleclicksearch2` library allows access to all features of the *Google doubleclicksearch* service. -This documentation was generated from *doubleclicksearch* crate version *0.1.6+20150303*, where *20150303* is the exact revision of the *doubleclicksearch:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *doubleclicksearch* crate version *0.1.7+20150303*, where *20150303* is the exact revision of the *doubleclicksearch:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *doubleclicksearch* *v2* API can be found at the [official documentation site](https://developers.google.com/doubleclick-search/). @@ -168,7 +168,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_doubleclicksearch2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_doubleclicksearch2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/doubleclicksearch2/src/cmn.rs b/gen/doubleclicksearch2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/doubleclicksearch2/src/cmn.rs +++ b/gen/doubleclicksearch2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/doubleclicksearch2/src/lib.rs b/gen/doubleclicksearch2/src/lib.rs index 12bd60ce24..2add31d217 100644 --- a/gen/doubleclicksearch2/src/lib.rs +++ b/gen/doubleclicksearch2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *doubleclicksearch* crate version *0.1.6+20150303*, where *20150303* is the exact revision of the *doubleclicksearch:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *doubleclicksearch* crate version *0.1.7+20150303*, where *20150303* is the exact revision of the *doubleclicksearch:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *doubleclicksearch* *v2* API can be found at the //! [official documentation site](https://developers.google.com/doubleclick-search/). @@ -169,7 +169,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -178,7 +178,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -194,6 +193,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -310,7 +310,7 @@ impl<'a, C, A> Doubleclicksearch<C, A> Doubleclicksearch { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -325,7 +325,7 @@ impl<'a, C, A> Doubleclicksearch<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1235,6 +1235,7 @@ impl<'a, C, A> ConversionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ConversionList)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1265,11 +1266,20 @@ impl<'a, C, A> ConversionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1292,7 +1302,7 @@ impl<'a, C, A> ConversionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1543,7 +1553,7 @@ impl<'a, C, A> ConversionGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1565,7 +1575,7 @@ impl<'a, C, A> ConversionGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1821,6 +1831,7 @@ impl<'a, C, A> ConversionUpdateAvailabilityCall<'a, C, A> where C: BorrowMut<hyp /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, UpdateAvailabilityResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1851,11 +1862,20 @@ impl<'a, C, A> ConversionUpdateAvailabilityCall<'a, C, A> where C: BorrowMut<hyp if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1878,7 +1898,7 @@ impl<'a, C, A> ConversionUpdateAvailabilityCall<'a, C, A> where C: BorrowMut<hyp request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2055,6 +2075,7 @@ impl<'a, C, A> ConversionPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ConversionList)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2092,11 +2113,20 @@ impl<'a, C, A> ConversionPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2119,7 +2149,7 @@ impl<'a, C, A> ConversionPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2359,6 +2389,7 @@ impl<'a, C, A> ConversionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ConversionList)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2389,11 +2420,20 @@ impl<'a, C, A> ConversionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2416,7 +2456,7 @@ impl<'a, C, A> ConversionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2637,7 +2677,7 @@ impl<'a, C, A> SavedColumnListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2659,7 +2699,7 @@ impl<'a, C, A> SavedColumnListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2890,7 +2930,7 @@ impl<'a, C, A> ReportGetFileCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2912,7 +2952,7 @@ impl<'a, C, A> ReportGetFileCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3080,6 +3120,7 @@ impl<'a, C, A> ReportGenerateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Report)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3110,11 +3151,20 @@ impl<'a, C, A> ReportGenerateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3137,7 +3187,7 @@ impl<'a, C, A> ReportGenerateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3356,7 +3406,7 @@ impl<'a, C, A> ReportGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3378,7 +3428,7 @@ impl<'a, C, A> ReportGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3546,6 +3596,7 @@ impl<'a, C, A> ReportRequestCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Report)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3576,11 +3627,20 @@ impl<'a, C, A> ReportRequestCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3603,7 +3663,7 @@ impl<'a, C, A> ReportRequestCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) diff --git a/gen/drive2-cli/Cargo.toml b/gen/drive2-cli/Cargo.toml index 6717c81aa4..1aa1148166 100644 --- a/gen/drive2-cli/Cargo.toml +++ b/gen/drive2-cli/Cargo.toml @@ -17,13 +17,14 @@ keywords = ["drive", "google", "cli"] name = "drive2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -clap = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-drive2] path = "../drive2" diff --git a/gen/drive2-cli/README.md b/gen/drive2-cli/README.md index 3fa68af848..35ac615658 100644 --- a/gen/drive2-cli/README.md +++ b/gen/drive2-cli/README.md @@ -93,9 +93,6 @@ drive2 [options] update <file-id> <revision-id> (-r <kv>)... [-p <v>]... [-o <out>] drive2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_drive2_cli - Configuration: [--scope <url>]... Specify the authentication a method should be executed in. Each scope diff --git a/gen/drive2-cli/src/cmn.rs b/gen/drive2-cli/src/cmn.rs index f784b283db..3335e7b6bd 100644 --- a/gen/drive2-cli/src/cmn.rs +++ b/gen/drive2-cli/src/cmn.rs @@ -4,6 +4,7 @@ use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; use serde::json; use mime::Mime; use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -18,14 +19,54 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + pub enum CallType { Upload(UploadProtocol), Standard, } -pub enum UploadProtocol { - Simple, - Resumable, +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } } impl AsRef<str> for UploadProtocol { @@ -46,18 +87,6 @@ impl AsRef<str> for CallType { } } -impl FromStr for UploadProtocol { - type Err = String; - - fn from_str(s: &str) -> Result<UploadProtocol, String> { - match s { - "simple" => Ok(UploadProtocol::Simple), - "resumable" => Ok(UploadProtocol::Resumable), - _ => Err(format!("Protocol '{}' is unknown", s)), - } - } -} - #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -129,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -153,7 +225,7 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } -pub fn protocol_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { CallType::Upload( match UploadProtocol::from_str(name) { Ok(up) => up, @@ -282,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -304,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -327,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -338,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -347,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -363,7 +448,7 @@ impl fmt::Display for FieldError { pub enum CLIError { Configuration(ConfigurationError), ParseError(&'static str, &'static str, String, String), - UnknownParameter(String), + UnknownParameter(String, Vec<&'static str>), InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), @@ -379,18 +464,24 @@ impl fmt::Display for CLIError { CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) - => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}", proto_name, valid_names.connect(", ")), + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, - CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command"), - CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command", cmd), + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } diff --git a/gen/drive2-cli/src/main.rs b/gen/drive2-cli/src/main.rs index d1043e9554..d13cc85146 100644 --- a/gen/drive2-cli/src/main.rs +++ b/gen/drive2-cli/src/main.rs @@ -4,12 +4,14 @@ #![feature(plugin, exit_status)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] +#[macro_use] extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_drive2 as api; use std::env; @@ -20,7 +22,7 @@ mod cmn; use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, - protocol_from_str}; + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; @@ -37,6 +39,8 @@ enum DoitError { struct Engine<'n, 'a> { opt: ArgMatches<'n, 'a>, hub: api::Drive<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } @@ -56,22 +60,21 @@ impl<'n, 'a> Engine<'n, 'a> { "include-subscribed" => { call = call.include_subscribed(arg_from_str(value.unwrap_or("false"), err, "include-subscribed", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["include-subscribed", "max-change-id-count", "start-change-id"] + )); + } + } } } let protocol = CallType::Standard; @@ -92,7 +95,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -105,22 +110,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -141,7 +145,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -163,22 +169,21 @@ impl<'n, 'a> Engine<'n, 'a> { "app-filter-extensions" => { call = call.app_filter_extensions(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language-code", "app-filter-extensions", "app-filter-mime-types"] + )); + } + } } } let protocol = CallType::Standard; @@ -199,7 +204,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -212,22 +219,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -248,7 +254,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -276,22 +284,21 @@ impl<'n, 'a> Engine<'n, 'a> { "include-deleted" => { call = call.include_deleted(arg_from_str(value.unwrap_or("false"), err, "include-deleted", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "include-deleted", "max-results", "start-change-id", "include-subscribed"] + )); + } + } } } let protocol = CallType::Standard; @@ -312,7 +319,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -374,7 +383,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -397,22 +407,21 @@ impl<'n, 'a> Engine<'n, 'a> { "include-deleted" => { call = call.include_deleted(arg_from_str(value.unwrap_or("false"), err, "include-deleted", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "include-deleted", "max-results", "start-change-id", "include-subscribed"] + )); + } + } } } let protocol = CallType::Standard; @@ -433,7 +442,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -495,7 +506,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -503,22 +515,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -547,22 +558,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -591,22 +601,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -627,7 +636,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -667,7 +678,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["child-link", "id", "kind", "self-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -675,22 +687,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -711,7 +722,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -733,22 +746,21 @@ impl<'n, 'a> Engine<'n, 'a> { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["q", "page-token", "max-results"] + )); + } + } } } let protocol = CallType::Standard; @@ -769,7 +781,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -782,22 +796,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -829,22 +842,21 @@ impl<'n, 'a> Engine<'n, 'a> { "include-deleted" => { call = call.include_deleted(arg_from_str(value.unwrap_or("false"), err, "include-deleted", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["include-deleted"] + )); + } + } } } let protocol = CallType::Standard; @@ -865,7 +877,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -990,7 +1004,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.file_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["anchor", "author", "comment-id", "content", "context", "created-date", "deleted", "display-name", "email-address", "file-id", "file-title", "html-content", "is-authenticated-user", "kind", "modified-date", "permission-id", "picture", "self-link", "status", "type", "url", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -998,22 +1013,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -1034,7 +1048,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -1059,22 +1075,21 @@ impl<'n, 'a> Engine<'n, 'a> { "include-deleted" => { call = call.include_deleted(arg_from_str(value.unwrap_or("false"), err, "include-deleted", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["updated-min", "include-deleted", "max-results", "page-token"] + )); + } + } } } let protocol = CallType::Standard; @@ -1095,7 +1110,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -1220,7 +1237,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.file_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["anchor", "author", "comment-id", "content", "context", "created-date", "deleted", "display-name", "email-address", "file-id", "file-title", "html-content", "is-authenticated-user", "kind", "modified-date", "permission-id", "picture", "self-link", "status", "type", "url", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -1228,22 +1246,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -1264,7 +1281,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -1389,7 +1408,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.file_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["anchor", "author", "comment-id", "content", "context", "created-date", "deleted", "display-name", "email-address", "file-id", "file-title", "html-content", "is-authenticated-user", "kind", "modified-date", "permission-id", "picture", "self-link", "status", "type", "url", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -1397,22 +1417,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -1433,7 +1452,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -1936,7 +1957,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.modified_date = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["additional-roles", "alternate-link", "altitude", "aperture", "app-data-contents", "auth-key", "camera-make", "camera-model", "color-space", "copyable", "created-date", "date", "default-open-with-link", "description", "display-name", "domain", "download-url", "duration-millis", "editable", "email-address", "embed-link", "etag", "explicitly-trashed", "export-links", "exposure-bias", "exposure-mode", "exposure-time", "file-extension", "file-size", "flash-used", "focal-length", "folder-color-rgb", "head-revision-id", "height", "hidden", "icon-link", "id", "image", "image-media-metadata", "indexable-text", "is-authenticated-user", "iso-speed", "kind", "labels", "last-modifying-user", "last-modifying-user-name", "last-viewed-by-me-date", "latitude", "lens", "location", "longitude", "marked-viewed-by-me-date", "max-aperture-value", "md5-checksum", "metering-mode", "mime-type", "modified-by-me-date", "modified-date", "name", "open-with-links", "original-filename", "owner-names", "permission-id", "photo-link", "picture", "quota-bytes-used", "restricted", "role", "rotation", "self-link", "sensor", "shared", "shared-with-me-date", "sharing-user", "starred", "subject-distance", "text", "thumbnail", "thumbnail-link", "title", "trashed", "type", "url", "user-permission", "value", "version", "video-media-metadata", "viewed", "web-content-link", "web-view-link", "white-balance", "width", "with-link", "writers-can-share"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -1965,22 +1987,21 @@ impl<'n, 'a> Engine<'n, 'a> { "convert" => { call = call.convert(arg_from_str(value.unwrap_or("false"), err, "convert", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["convert", "ocr-language", "visibility", "pinned", "ocr", "timed-text-track-name", "timed-text-language"] + )); + } + } } } let protocol = CallType::Standard; @@ -2001,7 +2022,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -2014,22 +2037,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -2058,22 +2080,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -2115,25 +2136,24 @@ impl<'n, 'a> Engine<'n, 'a> { "acknowledge-abuse" => { call = call.acknowledge_abuse(arg_from_str(value.unwrap_or("false"), err, "acknowledge-abuse", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["revision-id", "update-viewed-date", "acknowledge-abuse", "projection"] + )); + } + } } } let protocol = CallType::Standard; @@ -2155,7 +2175,9 @@ impl<'n, 'a> Engine<'n, 'a> { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { if !download_mode { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); } else { io::copy(&mut response, &mut ostream).unwrap(); } @@ -2661,7 +2683,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.modified_date = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["additional-roles", "alternate-link", "altitude", "aperture", "app-data-contents", "auth-key", "camera-make", "camera-model", "color-space", "copyable", "created-date", "date", "default-open-with-link", "description", "display-name", "domain", "download-url", "duration-millis", "editable", "email-address", "embed-link", "etag", "explicitly-trashed", "export-links", "exposure-bias", "exposure-mode", "exposure-time", "file-extension", "file-size", "flash-used", "focal-length", "folder-color-rgb", "head-revision-id", "height", "hidden", "icon-link", "id", "image", "image-media-metadata", "indexable-text", "is-authenticated-user", "iso-speed", "kind", "labels", "last-modifying-user", "last-modifying-user-name", "last-viewed-by-me-date", "latitude", "lens", "location", "longitude", "marked-viewed-by-me-date", "max-aperture-value", "md5-checksum", "metering-mode", "mime-type", "modified-by-me-date", "modified-date", "name", "open-with-links", "original-filename", "owner-names", "permission-id", "photo-link", "picture", "quota-bytes-used", "restricted", "role", "rotation", "self-link", "sensor", "shared", "shared-with-me-date", "sharing-user", "starred", "subject-distance", "text", "thumbnail", "thumbnail-link", "title", "trashed", "type", "url", "user-permission", "value", "version", "video-media-metadata", "viewed", "web-content-link", "web-view-link", "white-balance", "width", "with-link", "writers-can-share"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -2693,26 +2716,25 @@ impl<'n, 'a> Engine<'n, 'a> { "convert" => { call = call.convert(arg_from_str(value.unwrap_or("false"), err, "convert", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["convert", "use-content-as-indexable-text", "ocr-language", "visibility", "pinned", "ocr", "timed-text-track-name", "timed-text-language"] + )); + } + } } } let vals = opt.values_of("mode").unwrap(); - let protocol = protocol_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); let mut input_file = input_file_from_opts(vals[1], err); let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { @@ -2733,7 +2755,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -2761,22 +2785,21 @@ impl<'n, 'a> Engine<'n, 'a> { "corpus" => { call = call.corpus(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["q", "page-token", "corpus", "projection", "max-results"] + )); + } + } } } let protocol = CallType::Standard; @@ -2797,7 +2820,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -3300,7 +3325,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.modified_date = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["additional-roles", "alternate-link", "altitude", "aperture", "app-data-contents", "auth-key", "camera-make", "camera-model", "color-space", "copyable", "created-date", "date", "default-open-with-link", "description", "display-name", "domain", "download-url", "duration-millis", "editable", "email-address", "embed-link", "etag", "explicitly-trashed", "export-links", "exposure-bias", "exposure-mode", "exposure-time", "file-extension", "file-size", "flash-used", "focal-length", "folder-color-rgb", "head-revision-id", "height", "hidden", "icon-link", "id", "image", "image-media-metadata", "indexable-text", "is-authenticated-user", "iso-speed", "kind", "labels", "last-modifying-user", "last-modifying-user-name", "last-viewed-by-me-date", "latitude", "lens", "location", "longitude", "marked-viewed-by-me-date", "max-aperture-value", "md5-checksum", "metering-mode", "mime-type", "modified-by-me-date", "modified-date", "name", "open-with-links", "original-filename", "owner-names", "permission-id", "photo-link", "picture", "quota-bytes-used", "restricted", "role", "rotation", "self-link", "sensor", "shared", "shared-with-me-date", "sharing-user", "starred", "subject-distance", "text", "thumbnail", "thumbnail-link", "title", "trashed", "type", "url", "user-permission", "value", "version", "video-media-metadata", "viewed", "web-content-link", "web-view-link", "white-balance", "width", "with-link", "writers-can-share"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -3344,22 +3370,21 @@ impl<'n, 'a> Engine<'n, 'a> { "add-parents" => { call = call.add_parents(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["add-parents", "convert", "ocr", "set-modified-date", "use-content-as-indexable-text", "ocr-language", "new-revision", "pinned", "remove-parents", "update-viewed-date", "timed-text-track-name", "timed-text-language"] + )); + } + } } } let protocol = CallType::Standard; @@ -3380,7 +3405,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -3393,22 +3420,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -3429,7 +3455,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -3442,22 +3470,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -3478,7 +3505,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -3491,22 +3520,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -3527,7 +3555,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4030,7 +4060,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.modified_date = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["additional-roles", "alternate-link", "altitude", "aperture", "app-data-contents", "auth-key", "camera-make", "camera-model", "color-space", "copyable", "created-date", "date", "default-open-with-link", "description", "display-name", "domain", "download-url", "duration-millis", "editable", "email-address", "embed-link", "etag", "explicitly-trashed", "export-links", "exposure-bias", "exposure-mode", "exposure-time", "file-extension", "file-size", "flash-used", "focal-length", "folder-color-rgb", "head-revision-id", "height", "hidden", "icon-link", "id", "image", "image-media-metadata", "indexable-text", "is-authenticated-user", "iso-speed", "kind", "labels", "last-modifying-user", "last-modifying-user-name", "last-viewed-by-me-date", "latitude", "lens", "location", "longitude", "marked-viewed-by-me-date", "max-aperture-value", "md5-checksum", "metering-mode", "mime-type", "modified-by-me-date", "modified-date", "name", "open-with-links", "original-filename", "owner-names", "permission-id", "photo-link", "picture", "quota-bytes-used", "restricted", "role", "rotation", "self-link", "sensor", "shared", "shared-with-me-date", "sharing-user", "starred", "subject-distance", "text", "thumbnail", "thumbnail-link", "title", "trashed", "type", "url", "user-permission", "value", "version", "video-media-metadata", "viewed", "web-content-link", "web-view-link", "white-balance", "width", "with-link", "writers-can-share"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -4074,26 +4105,25 @@ impl<'n, 'a> Engine<'n, 'a> { "add-parents" => { call = call.add_parents(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["add-parents", "convert", "ocr", "set-modified-date", "use-content-as-indexable-text", "ocr-language", "new-revision", "pinned", "remove-parents", "update-viewed-date", "timed-text-track-name", "timed-text-language"] + )); + } + } } } let vals = opt.values_of("mode").unwrap(); - let protocol = protocol_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); let mut input_file = input_file_from_opts(vals[1], err); let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { @@ -4114,7 +4144,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4176,7 +4208,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -4197,25 +4230,24 @@ impl<'n, 'a> Engine<'n, 'a> { "acknowledge-abuse" => { call = call.acknowledge_abuse(arg_from_str(value.unwrap_or("false"), err, "acknowledge-abuse", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["revision-id", "update-viewed-date", "acknowledge-abuse", "projection"] + )); + } + } } } let protocol = CallType::Standard; @@ -4237,7 +4269,9 @@ impl<'n, 'a> Engine<'n, 'a> { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { if !download_mode { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); } else { io::copy(&mut response, &mut ostream).unwrap(); } @@ -4253,22 +4287,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -4297,22 +4330,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -4333,7 +4365,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4376,7 +4410,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.parent_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "is-root", "kind", "parent-link", "self-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -4384,22 +4419,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -4420,7 +4454,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4433,22 +4469,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -4469,7 +4504,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4482,22 +4519,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -4526,22 +4562,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -4562,7 +4597,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4575,22 +4612,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -4611,7 +4647,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4684,7 +4722,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["additional-roles", "auth-key", "domain", "email-address", "etag", "id", "kind", "name", "photo-link", "role", "self-link", "type", "value", "with-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -4698,22 +4737,21 @@ impl<'n, 'a> Engine<'n, 'a> { "email-message" => { call = call.email_message(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["email-message", "send-notification-emails"] + )); + } + } } } let protocol = CallType::Standard; @@ -4734,7 +4772,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4747,22 +4787,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -4783,7 +4822,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4856,7 +4897,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["additional-roles", "auth-key", "domain", "email-address", "etag", "id", "kind", "name", "photo-link", "role", "self-link", "type", "value", "with-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -4867,22 +4909,21 @@ impl<'n, 'a> Engine<'n, 'a> { "transfer-ownership" => { call = call.transfer_ownership(arg_from_str(value.unwrap_or("false"), err, "transfer-ownership", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["transfer-ownership"] + )); + } + } } } let protocol = CallType::Standard; @@ -4903,7 +4944,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4976,7 +5019,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["additional-roles", "auth-key", "domain", "email-address", "etag", "id", "kind", "name", "photo-link", "role", "self-link", "type", "value", "with-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -4987,22 +5031,21 @@ impl<'n, 'a> Engine<'n, 'a> { "transfer-ownership" => { call = call.transfer_ownership(arg_from_str(value.unwrap_or("false"), err, "transfer-ownership", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["transfer-ownership"] + )); + } + } } } let protocol = CallType::Standard; @@ -5023,7 +5066,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -5039,22 +5084,21 @@ impl<'n, 'a> Engine<'n, 'a> { "visibility" => { call = call.visibility(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["visibility"] + )); + } + } } } let protocol = CallType::Standard; @@ -5086,22 +5130,21 @@ impl<'n, 'a> Engine<'n, 'a> { "visibility" => { call = call.visibility(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["visibility"] + )); + } + } } } let protocol = CallType::Standard; @@ -5122,7 +5165,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -5168,7 +5213,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "key", "kind", "self-link", "value", "visibility"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -5176,22 +5222,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -5212,7 +5257,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -5225,22 +5272,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -5261,7 +5307,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -5307,7 +5355,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "key", "kind", "self-link", "value", "visibility"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -5318,22 +5367,21 @@ impl<'n, 'a> Engine<'n, 'a> { "visibility" => { call = call.visibility(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["visibility"] + )); + } + } } } let protocol = CallType::Standard; @@ -5354,7 +5402,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -5400,7 +5450,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "key", "kind", "self-link", "value", "visibility"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -5411,22 +5462,21 @@ impl<'n, 'a> Engine<'n, 'a> { "visibility" => { call = call.visibility(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["visibility"] + )); + } + } } } let protocol = CallType::Standard; @@ -5447,7 +5497,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -5464,25 +5516,24 @@ impl<'n, 'a> Engine<'n, 'a> { "revision" => { call = call.revision(arg_from_str(value.unwrap_or("-0"), err, "revision", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["revision"] + )); + } + } } } let protocol = CallType::Standard; @@ -5522,26 +5573,25 @@ impl<'n, 'a> Engine<'n, 'a> { "base-revision" => { call = call.base_revision(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["base-revision"] + )); + } + } } } let vals = opt.values_of("mode").unwrap(); - let protocol = protocol_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); let mut input_file = input_file_from_opts(vals[1], err); let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { @@ -5570,22 +5620,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -5617,22 +5666,21 @@ impl<'n, 'a> Engine<'n, 'a> { "include-deleted" => { call = call.include_deleted(arg_from_str(value.unwrap_or("false"), err, "include-deleted", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["include-deleted"] + )); + } + } } } let protocol = CallType::Standard; @@ -5653,7 +5701,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -5749,7 +5799,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.created_date = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author", "content", "created-date", "deleted", "display-name", "email-address", "html-content", "is-authenticated-user", "kind", "modified-date", "permission-id", "picture", "reply-id", "url", "verb"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -5757,22 +5808,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -5793,7 +5843,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -5815,22 +5867,21 @@ impl<'n, 'a> Engine<'n, 'a> { "include-deleted" => { call = call.include_deleted(arg_from_str(value.unwrap_or("false"), err, "include-deleted", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "include-deleted", "max-results"] + )); + } + } } } let protocol = CallType::Standard; @@ -5851,7 +5902,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -5947,7 +6000,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.created_date = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author", "content", "created-date", "deleted", "display-name", "email-address", "html-content", "is-authenticated-user", "kind", "modified-date", "permission-id", "picture", "reply-id", "url", "verb"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -5955,22 +6009,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -5991,7 +6044,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -6087,7 +6142,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.created_date = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author", "content", "created-date", "deleted", "display-name", "email-address", "html-content", "is-authenticated-user", "kind", "modified-date", "permission-id", "picture", "reply-id", "url", "verb"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -6095,22 +6151,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -6131,7 +6186,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -6144,22 +6201,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -6188,22 +6244,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -6224,7 +6279,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -6237,22 +6294,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -6273,7 +6329,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -6405,7 +6463,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.published = Some(arg_from_str(value.unwrap_or("false"), err, "published", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["display-name", "download-url", "email-address", "etag", "export-links", "file-size", "id", "is-authenticated-user", "kind", "last-modifying-user", "last-modifying-user-name", "md5-checksum", "mime-type", "modified-date", "original-filename", "permission-id", "picture", "pinned", "publish-auto", "published", "published-link", "published-outside-domain", "self-link", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -6413,22 +6472,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -6449,7 +6507,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -6581,7 +6641,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.published = Some(arg_from_str(value.unwrap_or("false"), err, "published", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["display-name", "download-url", "email-address", "etag", "export-links", "file-size", "id", "is-authenticated-user", "kind", "last-modifying-user", "last-modifying-user-name", "md5-checksum", "mime-type", "modified-date", "original-filename", "permission-id", "picture", "pinned", "publish-auto", "published", "published-link", "published-outside-domain", "self-link", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -6589,22 +6650,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -6625,7 +6685,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -6973,6 +7035,13 @@ impl<'n, 'a> Engine<'n, 'a> { let engine = Engine { opt: opt, hub: api::Drive::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { @@ -6994,1441 +7063,1559 @@ fn main() { let upload_value_names = ["mode", "file"]; let arg_data = [ ("about", "methods: 'get'", vec![ - ("get", Some("Gets the information about the current user along with Drive API settings"), + ("get", + Some(r##"Gets the information about the current user along with Drive API settings"##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/about_get", vec![ - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("apps", "methods: 'get' and 'list'", vec![ - ("get", Some("Gets a specific app."), + ("get", + Some(r##"Gets a specific app."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/apps_get", vec![ - (Some("app-id"), + (Some(r##"app-id"##), None, - Some("The ID of the app."), + Some(r##"The ID of the app."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Lists a user's installed apps."), + ("list", + Some(r##"Lists a user's installed apps."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/apps_list", vec![ - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("changes", "methods: 'get', 'list' and 'watch'", vec![ - ("get", Some("Gets a specific change."), + ("get", + Some(r##"Gets a specific change."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/changes_get", vec![ - (Some("change-id"), + (Some(r##"change-id"##), None, - Some("The ID of the change."), + Some(r##"The ID of the change."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Lists the changes for a user."), + ("list", + Some(r##"Lists the changes for a user."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/changes_list", vec![ - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("watch", Some("Subscribe to changes for a user."), + ("watch", + Some(r##"Subscribe to changes for a user."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/changes_watch", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("channels", "methods: 'stop'", vec![ - ("stop", Some("Stop watching resources through this channel"), + ("stop", + Some(r##"Stop watching resources through this channel"##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/channels_stop", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), ]), ("children", "methods: 'delete', 'get', 'insert' and 'list'", vec![ - ("delete", Some("Removes a child from a folder."), + ("delete", + Some(r##"Removes a child from a folder."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/children_delete", vec![ - (Some("folder-id"), + (Some(r##"folder-id"##), None, - Some("The ID of the folder."), + Some(r##"The ID of the folder."##), Some(true), Some(false)), - (Some("child-id"), + (Some(r##"child-id"##), None, - Some("The ID of the child."), + Some(r##"The ID of the child."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("get", Some("Gets a specific child reference."), + ("get", + Some(r##"Gets a specific child reference."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/children_get", vec![ - (Some("folder-id"), + (Some(r##"folder-id"##), None, - Some("The ID of the folder."), + Some(r##"The ID of the folder."##), Some(true), Some(false)), - (Some("child-id"), + (Some(r##"child-id"##), None, - Some("The ID of the child."), + Some(r##"The ID of the child."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("insert", Some("Inserts a file into a folder."), + ("insert", + Some(r##"Inserts a file into a folder."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/children_insert", vec![ - (Some("folder-id"), + (Some(r##"folder-id"##), None, - Some("The ID of the folder."), + Some(r##"The ID of the folder."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Lists a folder's children."), + ("list", + Some(r##"Lists a folder's children."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/children_list", vec![ - (Some("folder-id"), + (Some(r##"folder-id"##), None, - Some("The ID of the folder."), + Some(r##"The ID of the folder."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("comments", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ - ("delete", Some("Deletes a comment."), + ("delete", + Some(r##"Deletes a comment."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/comments_delete", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("comment-id"), + (Some(r##"comment-id"##), None, - Some("The ID of the comment."), + Some(r##"The ID of the comment."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("get", Some("Gets a comment by ID."), + ("get", + Some(r##"Gets a comment by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/comments_get", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("comment-id"), + (Some(r##"comment-id"##), None, - Some("The ID of the comment."), + Some(r##"The ID of the comment."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("insert", Some("Creates a new comment on the given file."), + ("insert", + Some(r##"Creates a new comment on the given file."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/comments_insert", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Lists a file's comments."), + ("list", + Some(r##"Lists a file's comments."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/comments_list", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("patch", Some("Updates an existing comment. This method supports patch semantics."), + ("patch", + Some(r##"Updates an existing comment. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/comments_patch", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("comment-id"), + (Some(r##"comment-id"##), None, - Some("The ID of the comment."), + Some(r##"The ID of the comment."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Updates an existing comment."), + ("update", + Some(r##"Updates an existing comment."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/comments_update", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("comment-id"), + (Some(r##"comment-id"##), None, - Some("The ID of the comment."), + Some(r##"The ID of the comment."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("files", "methods: 'copy', 'delete', 'empty-trash', 'get', 'insert', 'list', 'patch', 'touch', 'trash', 'untrash', 'update' and 'watch'", vec![ - ("copy", Some("Creates a copy of the specified file."), + ("copy", + Some(r##"Creates a copy of the specified file."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/files_copy", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file to copy."), + Some(r##"The ID of the file to copy."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("delete", Some("Permanently deletes a file by ID. Skips the trash. The currently authenticated user must own the file."), + ("delete", + Some(r##"Permanently deletes a file by ID. Skips the trash. The currently authenticated user must own the file."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/files_delete", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file to delete."), + Some(r##"The ID of the file to delete."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("empty-trash", Some("Permanently deletes all of the user's trashed files."), + ("empty-trash", + Some(r##"Permanently deletes all of the user's trashed files."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/files_empty-trash", vec![ - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("get", Some("Gets a file's metadata by ID."), + ("get", + Some(r##"Gets a file's metadata by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/files_get", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID for the file in question."), + Some(r##"The ID for the file in question."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("insert", Some("Insert a new file."), + ("insert", + Some(r##"Insert a new file."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/files_insert", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("mode"), - Some("u"), - Some("Specify the upload protocol (simple|resumable) and the file to upload"), + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Lists the user's files."), + ("list", + Some(r##"Lists the user's files."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/files_list", vec![ - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("patch", Some("Updates file metadata and/or content. This method supports patch semantics."), + ("patch", + Some(r##"Updates file metadata and/or content. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/files_patch", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file to update."), + Some(r##"The ID of the file to update."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("touch", Some("Set the file's updated time to the current server time."), + ("touch", + Some(r##"Set the file's updated time to the current server time."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/files_touch", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file to update."), + Some(r##"The ID of the file to update."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("trash", Some("Moves a file to the trash."), + ("trash", + Some(r##"Moves a file to the trash."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/files_trash", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file to trash."), + Some(r##"The ID of the file to trash."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("untrash", Some("Restores a file from the trash."), + ("untrash", + Some(r##"Restores a file from the trash."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/files_untrash", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file to untrash."), + Some(r##"The ID of the file to untrash."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Updates file metadata and/or content."), + ("update", + Some(r##"Updates file metadata and/or content."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/files_update", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file to update."), + Some(r##"The ID of the file to update."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("mode"), - Some("u"), - Some("Specify the upload protocol (simple|resumable) and the file to upload"), + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("watch", Some("Subscribe to changes on a file"), + ("watch", + Some(r##"Subscribe to changes on a file"##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/files_watch", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID for the file in question."), + Some(r##"The ID for the file in question."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("parents", "methods: 'delete', 'get', 'insert' and 'list'", vec![ - ("delete", Some("Removes a parent from a file."), + ("delete", + Some(r##"Removes a parent from a file."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/parents_delete", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("parent-id"), + (Some(r##"parent-id"##), None, - Some("The ID of the parent."), + Some(r##"The ID of the parent."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("get", Some("Gets a specific parent reference."), + ("get", + Some(r##"Gets a specific parent reference."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/parents_get", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("parent-id"), + (Some(r##"parent-id"##), None, - Some("The ID of the parent."), + Some(r##"The ID of the parent."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("insert", Some("Adds a parent folder for a file."), + ("insert", + Some(r##"Adds a parent folder for a file."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/parents_insert", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Lists a file's parents."), + ("list", + Some(r##"Lists a file's parents."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/parents_list", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("permissions", "methods: 'delete', 'get', 'get-id-for-email', 'insert', 'list', 'patch' and 'update'", vec![ - ("delete", Some("Deletes a permission from a file."), + ("delete", + Some(r##"Deletes a permission from a file."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/permissions_delete", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID for the file."), + Some(r##"The ID for the file."##), Some(true), Some(false)), - (Some("permission-id"), + (Some(r##"permission-id"##), None, - Some("The ID for the permission."), + Some(r##"The ID for the permission."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("get", Some("Gets a permission by ID."), + ("get", + Some(r##"Gets a permission by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/permissions_get", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID for the file."), + Some(r##"The ID for the file."##), Some(true), Some(false)), - (Some("permission-id"), + (Some(r##"permission-id"##), None, - Some("The ID for the permission."), + Some(r##"The ID for the permission."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("get-id-for-email", Some("Returns the permission ID for an email address."), + ("get-id-for-email", + Some(r##"Returns the permission ID for an email address."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/permissions_get-id-for-email", vec![ - (Some("email"), + (Some(r##"email"##), None, - Some("The email address for which to return a permission ID"), + Some(r##"The email address for which to return a permission ID"##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("insert", Some("Inserts a permission for a file."), + ("insert", + Some(r##"Inserts a permission for a file."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/permissions_insert", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID for the file."), + Some(r##"The ID for the file."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Lists a file's permissions."), + ("list", + Some(r##"Lists a file's permissions."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/permissions_list", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID for the file."), + Some(r##"The ID for the file."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("patch", Some("Updates a permission. This method supports patch semantics."), + ("patch", + Some(r##"Updates a permission. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/permissions_patch", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID for the file."), + Some(r##"The ID for the file."##), Some(true), Some(false)), - (Some("permission-id"), + (Some(r##"permission-id"##), None, - Some("The ID for the permission."), + Some(r##"The ID for the permission."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Updates a permission."), + ("update", + Some(r##"Updates a permission."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/permissions_update", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID for the file."), + Some(r##"The ID for the file."##), Some(true), Some(false)), - (Some("permission-id"), + (Some(r##"permission-id"##), None, - Some("The ID for the permission."), + Some(r##"The ID for the permission."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("properties", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ - ("delete", Some("Deletes a property."), + ("delete", + Some(r##"Deletes a property."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/properties_delete", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("property-key"), + (Some(r##"property-key"##), None, - Some("The key of the property."), + Some(r##"The key of the property."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("get", Some("Gets a property by its key."), + ("get", + Some(r##"Gets a property by its key."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/properties_get", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("property-key"), + (Some(r##"property-key"##), None, - Some("The key of the property."), + Some(r##"The key of the property."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("insert", Some("Adds a property to a file."), + ("insert", + Some(r##"Adds a property to a file."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/properties_insert", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Lists a file's properties."), + ("list", + Some(r##"Lists a file's properties."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/properties_list", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("patch", Some("Updates a property. This method supports patch semantics."), + ("patch", + Some(r##"Updates a property. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/properties_patch", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("property-key"), + (Some(r##"property-key"##), None, - Some("The key of the property."), + Some(r##"The key of the property."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Updates a property."), + ("update", + Some(r##"Updates a property."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/properties_update", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("property-key"), + (Some(r##"property-key"##), None, - Some("The key of the property."), + Some(r##"The key of the property."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("realtime", "methods: 'get' and 'update'", vec![ - ("get", Some("Exports the contents of the Realtime API data model associated with this file as JSON."), + ("get", + Some(r##"Exports the contents of the Realtime API data model associated with this file as JSON."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/realtime_get", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file that the Realtime API data model is associated with."), + Some(r##"The ID of the file that the Realtime API data model is associated with."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Overwrites the Realtime API data model associated with this file with the provided JSON data model."), + ("update", + Some(r##"Overwrites the Realtime API data model associated with this file with the provided JSON data model."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/realtime_update", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file that the Realtime API data model is associated with."), + Some(r##"The ID of the file that the Realtime API data model is associated with."##), Some(true), Some(false)), - (Some("mode"), - Some("u"), - Some("Specify the upload protocol (simple|resumable) and the file to upload"), + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), ]), ("replies", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ - ("delete", Some("Deletes a reply."), + ("delete", + Some(r##"Deletes a reply."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/replies_delete", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("comment-id"), + (Some(r##"comment-id"##), None, - Some("The ID of the comment."), + Some(r##"The ID of the comment."##), Some(true), Some(false)), - (Some("reply-id"), + (Some(r##"reply-id"##), None, - Some("The ID of the reply."), + Some(r##"The ID of the reply."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("get", Some("Gets a reply."), + ("get", + Some(r##"Gets a reply."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/replies_get", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("comment-id"), + (Some(r##"comment-id"##), None, - Some("The ID of the comment."), + Some(r##"The ID of the comment."##), Some(true), Some(false)), - (Some("reply-id"), + (Some(r##"reply-id"##), None, - Some("The ID of the reply."), + Some(r##"The ID of the reply."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("insert", Some("Creates a new reply to the given comment."), + ("insert", + Some(r##"Creates a new reply to the given comment."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/replies_insert", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("comment-id"), + (Some(r##"comment-id"##), None, - Some("The ID of the comment."), + Some(r##"The ID of the comment."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Lists all of the replies to a comment."), + ("list", + Some(r##"Lists all of the replies to a comment."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/replies_list", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("comment-id"), + (Some(r##"comment-id"##), None, - Some("The ID of the comment."), + Some(r##"The ID of the comment."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("patch", Some("Updates an existing reply. This method supports patch semantics."), + ("patch", + Some(r##"Updates an existing reply. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/replies_patch", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("comment-id"), + (Some(r##"comment-id"##), None, - Some("The ID of the comment."), + Some(r##"The ID of the comment."##), Some(true), Some(false)), - (Some("reply-id"), + (Some(r##"reply-id"##), None, - Some("The ID of the reply."), + Some(r##"The ID of the reply."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Updates an existing reply."), + ("update", + Some(r##"Updates an existing reply."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/replies_update", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("comment-id"), + (Some(r##"comment-id"##), None, - Some("The ID of the comment."), + Some(r##"The ID of the comment."##), Some(true), Some(false)), - (Some("reply-id"), + (Some(r##"reply-id"##), None, - Some("The ID of the reply."), + Some(r##"The ID of the reply."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("revisions", "methods: 'delete', 'get', 'list', 'patch' and 'update'", vec![ - ("delete", Some("Removes a revision."), + ("delete", + Some(r##"Removes a revision."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/revisions_delete", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("revision-id"), + (Some(r##"revision-id"##), None, - Some("The ID of the revision."), + Some(r##"The ID of the revision."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("get", Some("Gets a specific revision."), + ("get", + Some(r##"Gets a specific revision."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/revisions_get", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("revision-id"), + (Some(r##"revision-id"##), None, - Some("The ID of the revision."), + Some(r##"The ID of the revision."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Lists a file's revisions."), + ("list", + Some(r##"Lists a file's revisions."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/revisions_list", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID of the file."), + Some(r##"The ID of the file."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("patch", Some("Updates a revision. This method supports patch semantics."), + ("patch", + Some(r##"Updates a revision. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/revisions_patch", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID for the file."), + Some(r##"The ID for the file."##), Some(true), Some(false)), - (Some("revision-id"), + (Some(r##"revision-id"##), None, - Some("The ID for the revision."), + Some(r##"The ID for the revision."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Updates a revision."), + ("update", + Some(r##"Updates a revision."##), + "Details at http://byron.github.io/google-apis-rs/google_drive2_cli/revisions_update", vec![ - (Some("file-id"), + (Some(r##"file-id"##), None, - Some("The ID for the file."), + Some(r##"The ID for the file."##), Some(true), Some(false)), - (Some("revision-id"), + (Some(r##"revision-id"##), None, - Some("The ID for the revision."), + Some(r##"The ID for the revision."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), @@ -8465,11 +8652,12 @@ fn main() { for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { let mut mcmd = SubCommand::new(main_command_name).about(about); - for &(sub_command_name, ref desc, ref args) in subcommands { + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { let mut scmd = SubCommand::new(sub_command_name); if let &Some(desc) = desc { scmd = scmd.about(desc); } + scmd = scmd.after_help(url_info); for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { let arg_name_str = diff --git a/gen/drive2/Cargo.toml b/gen/drive2/Cargo.toml index 66802b4126..e317b4111f 100644 --- a/gen/drive2/Cargo.toml +++ b/gen/drive2/Cargo.toml @@ -15,9 +15,10 @@ keywords = ["drive", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/drive2/src/cmn.rs b/gen/drive2/src/cmn.rs index b65c5301bb..908bef39dc 100644 --- a/gen/drive2/src/cmn.rs +++ b/gen/drive2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -250,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -293,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -589,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -625,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/drive2/src/lib.rs b/gen/drive2/src/lib.rs index 911cc3e2b9..550543e691 100644 --- a/gen/drive2/src/lib.rs +++ b/gen/drive2/src/lib.rs @@ -255,6 +255,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -3671,6 +3672,7 @@ impl<'a, C, A> FileWatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Channel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3754,11 +3756,20 @@ impl<'a, C, A> FileWatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4007,6 +4018,7 @@ impl<'a, C, A> FileInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, File)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4069,11 +4081,20 @@ impl<'a, C, A> FileInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4478,7 +4499,7 @@ impl<'a, C, A> FileUntrashCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4683,6 +4704,7 @@ impl<'a, C, A> FileCopyCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, File)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4759,11 +4781,20 @@ impl<'a, C, A> FileCopyCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5064,7 +5095,7 @@ impl<'a, C, A> FileTrashCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5276,7 +5307,7 @@ impl<'a, C, A> FileEmptyTrashCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5494,7 +5525,7 @@ impl<'a, C, A> FileListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5758,7 +5789,7 @@ impl<'a, C, A> FileTouchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5975,6 +6006,7 @@ impl<'a, C, A> FileUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, File)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6074,11 +6106,20 @@ impl<'a, C, A> FileUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6520,7 +6561,7 @@ impl<'a, C, A> FileDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6725,6 +6766,7 @@ impl<'a, C, A> FilePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, File)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6816,11 +6858,20 @@ impl<'a, C, A> FilePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7197,7 +7248,7 @@ impl<'a, C, A> FileGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7453,7 +7504,7 @@ impl<'a, C, A> AboutGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7717,7 +7768,7 @@ impl<'a, C, A> RealtimeUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8062,7 +8113,7 @@ impl<'a, C, A> RealtimeGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8298,7 +8349,7 @@ impl<'a, C, A> AppGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth2 if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8526,7 +8577,7 @@ impl<'a, C, A> AppListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8777,7 +8828,7 @@ impl<'a, C, A> CommentDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9023,7 +9074,7 @@ impl<'a, C, A> CommentGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9231,6 +9282,7 @@ impl<'a, C, A> CommentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Comment)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9286,11 +9338,20 @@ impl<'a, C, A> CommentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9495,6 +9556,7 @@ impl<'a, C, A> CommentPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Comment)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9551,11 +9613,20 @@ impl<'a, C, A> CommentPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9770,6 +9841,7 @@ impl<'a, C, A> CommentUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Comment)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9826,11 +9898,20 @@ impl<'a, C, A> CommentUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10112,7 +10193,7 @@ impl<'a, C, A> CommentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10394,7 +10475,7 @@ impl<'a, C, A> ChildrenListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10656,7 +10737,7 @@ impl<'a, C, A> ChildrenGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10906,7 +10987,7 @@ impl<'a, C, A> ChildrenDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11097,6 +11178,7 @@ impl<'a, C, A> ChildrenInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ChildReference)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11152,11 +11234,20 @@ impl<'a, C, A> ChildrenInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11359,6 +11450,7 @@ impl<'a, C, A> ChannelStopCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11388,11 +11480,20 @@ impl<'a, C, A> ChannelStopCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11624,7 +11725,7 @@ impl<'a, C, A> ParentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11864,7 +11965,7 @@ impl<'a, C, A> ParentDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12055,6 +12156,7 @@ impl<'a, C, A> ParentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ParentReference)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12110,11 +12212,20 @@ impl<'a, C, A> ParentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12368,7 +12479,7 @@ impl<'a, C, A> ParentGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12571,6 +12682,7 @@ impl<'a, C, A> ReplyPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CommentReply)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12628,11 +12740,20 @@ impl<'a, C, A> ReplyPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12921,7 +13042,7 @@ impl<'a, C, A> ReplyListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13200,7 +13321,7 @@ impl<'a, C, A> ReplyGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13419,6 +13540,7 @@ impl<'a, C, A> ReplyInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CommentReply)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13475,11 +13597,20 @@ impl<'a, C, A> ReplyInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13744,7 +13875,7 @@ impl<'a, C, A> ReplyDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13947,6 +14078,7 @@ impl<'a, C, A> ReplyUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CommentReply)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14004,11 +14136,20 @@ impl<'a, C, A> ReplyUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14281,7 +14422,7 @@ impl<'a, C, A> PermissionDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14476,6 +14617,7 @@ impl<'a, C, A> PermissionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Permission)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14537,11 +14679,20 @@ impl<'a, C, A> PermissionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14762,6 +14913,7 @@ impl<'a, C, A> PermissionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Permission)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14821,11 +14973,20 @@ impl<'a, C, A> PermissionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15049,6 +15210,7 @@ impl<'a, C, A> PermissionPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Permission)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15108,11 +15270,20 @@ impl<'a, C, A> PermissionPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15381,7 +15552,7 @@ impl<'a, C, A> PermissionListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15622,7 +15793,7 @@ impl<'a, C, A> PermissionGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15871,7 +16042,7 @@ impl<'a, C, A> PermissionGetIdForEmailCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16071,6 +16242,7 @@ impl<'a, C, A> ChangeWatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Channel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -16116,11 +16288,20 @@ impl<'a, C, A> ChangeWatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -16396,7 +16577,7 @@ impl<'a, C, A> ChangeListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16660,7 +16841,7 @@ impl<'a, C, A> ChangeGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16854,6 +17035,7 @@ impl<'a, C, A> PropertyPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Property)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -16913,11 +17095,20 @@ impl<'a, C, A> PropertyPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17192,7 +17383,7 @@ impl<'a, C, A> PropertyDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17390,6 +17581,7 @@ impl<'a, C, A> PropertyInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Property)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17445,11 +17637,20 @@ impl<'a, C, A> PropertyInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17701,7 +17902,7 @@ impl<'a, C, A> PropertyListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17895,6 +18096,7 @@ impl<'a, C, A> PropertyUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Property)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17954,11 +18156,20 @@ impl<'a, C, A> PropertyUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -18234,7 +18445,7 @@ impl<'a, C, A> PropertyGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18492,7 +18703,7 @@ impl<'a, C, A> RevisionGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18742,7 +18953,7 @@ impl<'a, C, A> RevisionDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18934,6 +19145,7 @@ impl<'a, C, A> RevisionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Revision)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -18990,11 +19202,20 @@ impl<'a, C, A> RevisionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -19256,7 +19477,7 @@ impl<'a, C, A> RevisionListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19448,6 +19669,7 @@ impl<'a, C, A> RevisionPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Revision)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -19504,11 +19726,20 @@ impl<'a, C, A> RevisionPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); diff --git a/gen/fitness1-cli/Cargo.toml b/gen/fitness1-cli/Cargo.toml index be9e471130..cf49d0fd28 100644 --- a/gen/fitness1-cli/Cargo.toml +++ b/gen/fitness1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-fitness1-cli" -version = "0.1.0+20150326" +version = "0.2.0+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with fitness (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/fitness1-cli" @@ -17,15 +17,14 @@ keywords = ["fitness", "google", "cli"] name = "fitness1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-fitness1] path = "../fitness1" diff --git a/gen/fitness1-cli/README.md b/gen/fitness1-cli/README.md index af9b79b831..012c0c60f9 100644 --- a/gen/fitness1-cli/README.md +++ b/gen/fitness1-cli/README.md @@ -10,32 +10,34 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *fitness* API can be found at the +[official documentation site](https://developers.google.com/fit/rest/). + # Usage -This documentation was generated from the *fitness* API at revision *20150326*. The CLI is at version *0.1.0*. +This documentation was generated from the *fitness* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - fitness1 [options] users data-sources-create <user-id> -r <kv>... [-p <v>...] [-o <out>] - fitness1 [options] users data-sources-datasets-delete <user-id> <data-source-id> <dataset-id> [-p <v>...] - fitness1 [options] users data-sources-datasets-get <user-id> <data-source-id> <dataset-id> [-p <v>...] [-o <out>] - fitness1 [options] users data-sources-datasets-patch <user-id> <data-source-id> <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - fitness1 [options] users data-sources-delete <user-id> <data-source-id> [-p <v>...] [-o <out>] - fitness1 [options] users data-sources-get <user-id> <data-source-id> [-p <v>...] [-o <out>] - fitness1 [options] users data-sources-list <user-id> [-p <v>...] [-o <out>] - fitness1 [options] users data-sources-patch <user-id> <data-source-id> -r <kv>... [-p <v>...] [-o <out>] - fitness1 [options] users data-sources-update <user-id> <data-source-id> -r <kv>... [-p <v>...] [-o <out>] - fitness1 [options] users sessions-delete <user-id> <session-id> [-p <v>...] - fitness1 [options] users sessions-list <user-id> [-p <v>...] [-o <out>] - fitness1 [options] users sessions-update <user-id> <session-id> -r <kv>... [-p <v>...] [-o <out>] +fitness1 [options] + users + data-sources-create <user-id> (-r <kv>)... [-p <v>]... [-o <out>] + data-sources-datasets-delete <user-id> <data-source-id> <dataset-id> [-p <v>]... + data-sources-datasets-get <user-id> <data-source-id> <dataset-id> [-p <v>]... [-o <out>] + data-sources-datasets-patch <user-id> <data-source-id> <dataset-id> (-r <kv>)... [-p <v>]... [-o <out>] + data-sources-delete <user-id> <data-source-id> [-p <v>]... [-o <out>] + data-sources-get <user-id> <data-source-id> [-p <v>]... [-o <out>] + data-sources-list <user-id> [-p <v>]... [-o <out>] + data-sources-patch <user-id> <data-source-id> (-r <kv>)... [-p <v>]... [-o <out>] + data-sources-update <user-id> <data-source-id> (-r <kv>)... [-p <v>]... [-o <out>] + sessions-delete <user-id> <session-id> [-p <v>]... + sessions-list <user-id> [-p <v>]... [-o <out>] + sessions-update <user-id> <session-id> (-r <kv>)... [-p <v>]... [-o <out>] fitness1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_fitness1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/fitness1-cli/mkdocs.yml b/gen/fitness1-cli/mkdocs.yml index e4ffda32a7..e25316b797 100644 --- a/gen/fitness1-cli/mkdocs.yml +++ b/gen/fitness1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: fitness v0.1.0+20150326 +site_name: fitness v0.2.0+20150326 site_url: http://byron.github.io/google-apis-rs/google-fitness1-cli site_description: Write integrating applications with bcore diff --git a/gen/fitness1-cli/src/cmn.rs b/gen/fitness1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/fitness1-cli/src/cmn.rs +++ b/gen/fitness1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/fitness1-cli/src/main.rs b/gen/fitness1-cli/src/main.rs index b2021101f5..5af49ea255 100644 --- a/gen/fitness1-cli/src/main.rs +++ b/gen/fitness1-cli/src/main.rs @@ -2,80 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_fitness1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - fitness1 [options] users data-sources-create <user-id> -r <kv>... [-p <v>...] [-o <out>] - fitness1 [options] users data-sources-datasets-delete <user-id> <data-source-id> <dataset-id> [-p <v>...] - fitness1 [options] users data-sources-datasets-get <user-id> <data-source-id> <dataset-id> [-p <v>...] [-o <out>] - fitness1 [options] users data-sources-datasets-patch <user-id> <data-source-id> <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - fitness1 [options] users data-sources-delete <user-id> <data-source-id> [-p <v>...] [-o <out>] - fitness1 [options] users data-sources-get <user-id> <data-source-id> [-p <v>...] [-o <out>] - fitness1 [options] users data-sources-list <user-id> [-p <v>...] [-o <out>] - fitness1 [options] users data-sources-patch <user-id> <data-source-id> -r <kv>... [-p <v>...] [-o <out>] - fitness1 [options] users data-sources-update <user-id> <data-source-id> -r <kv>... [-p <v>...] [-o <out>] - fitness1 [options] users sessions-delete <user-id> <session-id> [-p <v>...] - fitness1 [options] users sessions-list <user-id> [-p <v>...] [-o <out>] - fitness1 [options] users sessions-update <user-id> <session-id> -r <kv>... [-p <v>...] [-o <out>] - fitness1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_fitness1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Fitness<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _users_data_sources_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _users_data_sources_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::DataSource::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -163,58 +138,63 @@ impl Engine { request.type_ = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["application", "data-stream-id", "data-stream-name", "data-type", "details-url", "device", "manufacturer", "model", "name", "package-name", "type", "uid", "version"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().data_sources_create(request, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().data_sources_create(request, opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_data_sources_datasets_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().data_sources_datasets_delete(&self.opt.arg_user_id, &self.opt.arg_data_source_id, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + fn _users_data_sources_datasets_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().data_sources_datasets_delete(opt.value_of("user-id").unwrap_or(""), opt.value_of("data-source-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "modified-time-millis" => { @@ -223,48 +203,47 @@ impl Engine { "current-time-millis" => { call = call.current_time_millis(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["modified-time-millis", "current-time-millis"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _users_data_sources_datasets_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().data_sources_datasets_get(&self.opt.arg_user_id, &self.opt.arg_data_source_id, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + fn _users_data_sources_datasets_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().data_sources_datasets_get(opt.value_of("user-id").unwrap_or(""), opt.value_of("data-source-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -273,52 +252,56 @@ impl Engine { "limit" => { call = call.limit(arg_from_str(value.unwrap_or("-0"), err, "limit", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "limit"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_data_sources_datasets_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_data_sources_datasets_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Dataset::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -346,204 +329,221 @@ impl Engine { request.data_source_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["data-source-id", "max-end-time-ns", "min-start-time-ns", "next-page-token"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().data_sources_datasets_patch(request, &self.opt.arg_user_id, &self.opt.arg_data_source_id, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().data_sources_datasets_patch(request, opt.value_of("user-id").unwrap_or(""), opt.value_of("data-source-id").unwrap_or(""), opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "current-time-millis" => { call = call.current_time_millis(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["current-time-millis"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_data_sources_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().data_sources_delete(&self.opt.arg_user_id, &self.opt.arg_data_source_id); - for parg in self.opt.arg_v.iter() { + fn _users_data_sources_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().data_sources_delete(opt.value_of("user-id").unwrap_or(""), opt.value_of("data-source-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_data_sources_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().data_sources_get(&self.opt.arg_user_id, &self.opt.arg_data_source_id); - for parg in self.opt.arg_v.iter() { + fn _users_data_sources_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().data_sources_get(opt.value_of("user-id").unwrap_or(""), opt.value_of("data-source-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_data_sources_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().data_sources_list(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _users_data_sources_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().data_sources_list(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "data-type-name" => { call = call.add_data_type_name(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["data-type-name"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_data_sources_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_data_sources_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::DataSource::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -631,60 +631,65 @@ impl Engine { request.type_ = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["application", "data-stream-id", "data-stream-name", "data-type", "details-url", "device", "manufacturer", "model", "name", "package-name", "type", "uid", "version"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().data_sources_patch(request, &self.opt.arg_user_id, &self.opt.arg_data_source_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().data_sources_patch(request, opt.value_of("user-id").unwrap_or(""), opt.value_of("data-source-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_data_sources_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_data_sources_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::DataSource::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -772,105 +777,109 @@ impl Engine { request.type_ = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["application", "data-stream-id", "data-stream-name", "data-type", "details-url", "device", "manufacturer", "model", "name", "package-name", "type", "uid", "version"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().data_sources_update(request, &self.opt.arg_user_id, &self.opt.arg_data_source_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().data_sources_update(request, opt.value_of("user-id").unwrap_or(""), opt.value_of("data-source-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_sessions_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().sessions_delete(&self.opt.arg_user_id, &self.opt.arg_session_id); - for parg in self.opt.arg_v.iter() { + fn _users_sessions_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().sessions_delete(opt.value_of("user-id").unwrap_or(""), opt.value_of("session-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "current-time-millis" => { call = call.current_time_millis(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["current-time-millis"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _users_sessions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().sessions_list(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _users_sessions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().sessions_list(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-time" => { @@ -885,52 +894,56 @@ impl Engine { "end-time" => { call = call.end_time(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "end-time", "include-deleted", "start-time"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_sessions_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_sessions_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Session::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -996,106 +1009,131 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["active-time-millis", "activity-type", "application", "description", "details-url", "end-time-millis", "id", "modified-time-millis", "name", "package-name", "start-time-millis", "version"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().sessions_update(request, &self.opt.arg_user_id, &self.opt.arg_session_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().sessions_update(request, opt.value_of("user-id").unwrap_or(""), opt.value_of("session-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "current-time-millis" => { call = call.current_time_millis(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["current-time-millis"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_users { - if self.opt.cmd_data_sources_create { - call_result = self._users_data_sources_create(dry_run, &mut err); - } else if self.opt.cmd_data_sources_datasets_delete { - call_result = self._users_data_sources_datasets_delete(dry_run, &mut err); - } else if self.opt.cmd_data_sources_datasets_get { - call_result = self._users_data_sources_datasets_get(dry_run, &mut err); - } else if self.opt.cmd_data_sources_datasets_patch { - call_result = self._users_data_sources_datasets_patch(dry_run, &mut err); - } else if self.opt.cmd_data_sources_delete { - call_result = self._users_data_sources_delete(dry_run, &mut err); - } else if self.opt.cmd_data_sources_get { - call_result = self._users_data_sources_get(dry_run, &mut err); - } else if self.opt.cmd_data_sources_list { - call_result = self._users_data_sources_list(dry_run, &mut err); - } else if self.opt.cmd_data_sources_patch { - call_result = self._users_data_sources_patch(dry_run, &mut err); - } else if self.opt.cmd_data_sources_update { - call_result = self._users_data_sources_update(dry_run, &mut err); - } else if self.opt.cmd_sessions_delete { - call_result = self._users_sessions_delete(dry_run, &mut err); - } else if self.opt.cmd_sessions_list { - call_result = self._users_sessions_list(dry_run, &mut err); - } else if self.opt.cmd_sessions_update { - call_result = self._users_sessions_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("users", Some(opt)) => { + match opt.subcommand() { + ("data-sources-create", Some(opt)) => { + call_result = self._users_data_sources_create(opt, dry_run, &mut err); + }, + ("data-sources-datasets-delete", Some(opt)) => { + call_result = self._users_data_sources_datasets_delete(opt, dry_run, &mut err); + }, + ("data-sources-datasets-get", Some(opt)) => { + call_result = self._users_data_sources_datasets_get(opt, dry_run, &mut err); + }, + ("data-sources-datasets-patch", Some(opt)) => { + call_result = self._users_data_sources_datasets_patch(opt, dry_run, &mut err); + }, + ("data-sources-delete", Some(opt)) => { + call_result = self._users_data_sources_delete(opt, dry_run, &mut err); + }, + ("data-sources-get", Some(opt)) => { + call_result = self._users_data_sources_get(opt, dry_run, &mut err); + }, + ("data-sources-list", Some(opt)) => { + call_result = self._users_data_sources_list(opt, dry_run, &mut err); + }, + ("data-sources-patch", Some(opt)) => { + call_result = self._users_data_sources_patch(opt, dry_run, &mut err); + }, + ("data-sources-update", Some(opt)) => { + call_result = self._users_data_sources_update(opt, dry_run, &mut err); + }, + ("sessions-delete", Some(opt)) => { + call_result = self._users_sessions_delete(opt, dry_run, &mut err); + }, + ("sessions-list", Some(opt)) => { + call_result = self._users_sessions_list(opt, dry_run, &mut err); + }, + ("sessions-update", Some(opt)) => { + call_result = self._users_sessions_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("users".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -1108,7 +1146,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1121,7 +1159,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1131,37 +1169,484 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Fitness::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("users", "methods: 'data-sources-create', 'data-sources-datasets-delete', 'data-sources-datasets-get', 'data-sources-datasets-patch', 'data-sources-delete', 'data-sources-get', 'data-sources-list', 'data-sources-patch', 'data-sources-update', 'sessions-delete', 'sessions-list' and 'sessions-update'", vec![ + ("data-sources-create", + Some(r##"Creates a new data source that is unique across all data sources belonging to this user. The data stream ID field can be omitted and will be generated by the server with the correct format. The data stream ID is an ordered combination of some fields from the data source. In addition to the data source fields reflected into the data source ID, the developer project number that is authenticated when creating the data source is included. This developer project number is obfuscated when read by any other developer reading public data types."##), + "Details at http://byron.github.io/google-apis-rs/google_fitness1_cli/users_data-sources-create", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"Create the data source for the person identified. Use me to indicate the authenticated user. Only me is supported at this time."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("data-sources-datasets-delete", + Some(r##"Performs an inclusive delete of all data points whose start and end times have any overlap with the time range specified by the dataset ID. For most data types, the entire data point will be deleted. For data types where the time span represents a consistent value (such as com.google.activity.segment), and a data point straddles either end point of the dataset, only the overlapping portion of the data point will be deleted."##), + "Details at http://byron.github.io/google-apis-rs/google_fitness1_cli/users_data-sources-datasets-delete", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"Delete a dataset for the person identified. Use me to indicate the authenticated user. Only me is supported at this time."##), + Some(true), + Some(false)), + + (Some(r##"data-source-id"##), + None, + Some(r##"The data stream ID of the data source that created the dataset."##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset identifier that is a composite of the minimum data point start time and maximum data point end time represented as nanoseconds from the epoch. The ID is formatted like: "startTime-endTime" where startTime and endTime are 64 bit integers."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("data-sources-datasets-get", + Some(r##"Returns a dataset containing all data points whose start and end times overlap with the specified range of the dataset minimum start time and maximum end time. Specifically, any data point whose start time is less than or equal to the dataset end time and whose end time is greater than or equal to the dataset start time."##), + "Details at http://byron.github.io/google-apis-rs/google_fitness1_cli/users_data-sources-datasets-get", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"Retrieve a dataset for the person identified. Use me to indicate the authenticated user. Only me is supported at this time."##), + Some(true), + Some(false)), + + (Some(r##"data-source-id"##), + None, + Some(r##"The data stream ID of the data source that created the dataset."##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset identifier that is a composite of the minimum data point start time and maximum data point end time represented as nanoseconds from the epoch. The ID is formatted like: "startTime-endTime" where startTime and endTime are 64 bit integers."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("data-sources-datasets-patch", + Some(r##"Adds data points to a dataset. The dataset need not be previously created. All points within the given dataset will be returned with subsquent calls to retrieve this dataset. Data points can belong to more than one dataset. This method does not use patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_fitness1_cli/users_data-sources-datasets-patch", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"Patch a dataset for the person identified. Use me to indicate the authenticated user. Only me is supported at this time."##), + Some(true), + Some(false)), + + (Some(r##"data-source-id"##), + None, + Some(r##"The data stream ID of the data source that created the dataset."##), + Some(true), + Some(false)), + + (Some(r##"dataset-id"##), + None, + Some(r##"Dataset identifier that is a composite of the minimum data point start time and maximum data point end time represented as nanoseconds from the epoch. The ID is formatted like: "startTime-endTime" where startTime and endTime are 64 bit integers."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("data-sources-delete", + Some(r##"Delete the data source if there are no datapoints associated with it"##), + "Details at http://byron.github.io/google-apis-rs/google_fitness1_cli/users_data-sources-delete", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"Retrieve a data source for the person identified. Use me to indicate the authenticated user. Only me is supported at this time."##), + Some(true), + Some(false)), + + (Some(r##"data-source-id"##), + None, + Some(r##"The data stream ID of the data source to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("data-sources-get", + Some(r##"Returns a data source identified by a data stream ID."##), + "Details at http://byron.github.io/google-apis-rs/google_fitness1_cli/users_data-sources-get", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"Retrieve a data source for the person identified. Use me to indicate the authenticated user. Only me is supported at this time."##), + Some(true), + Some(false)), + + (Some(r##"data-source-id"##), + None, + Some(r##"The data stream ID of the data source to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("data-sources-list", + Some(r##"Lists all data sources that are visible to the developer, using the OAuth scopes provided. The list is not exhaustive: the user may have private data sources that are only visible to other developers or calls using other scopes."##), + "Details at http://byron.github.io/google-apis-rs/google_fitness1_cli/users_data-sources-list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"List data sources for the person identified. Use me to indicate the authenticated user. Only me is supported at this time."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("data-sources-patch", + Some(r##"Updates a given data source. It is an error to modify the data source's data stream ID, data type, type, stream name or device information apart from the device version. Changing these fields would require a new unique data stream ID and separate data source. + + Data sources are identified by their data stream ID. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_fitness1_cli/users_data-sources-patch", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"Update the data source for the person identified. Use me to indicate the authenticated user. Only me is supported at this time."##), + Some(true), + Some(false)), + + (Some(r##"data-source-id"##), + None, + Some(r##"The data stream ID of the data source to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("data-sources-update", + Some(r##"Updates a given data source. It is an error to modify the data source's data stream ID, data type, type, stream name or device information apart from the device version. Changing these fields would require a new unique data stream ID and separate data source. + + Data sources are identified by their data stream ID."##), + "Details at http://byron.github.io/google-apis-rs/google_fitness1_cli/users_data-sources-update", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"Update the data source for the person identified. Use me to indicate the authenticated user. Only me is supported at this time."##), + Some(true), + Some(false)), + + (Some(r##"data-source-id"##), + None, + Some(r##"The data stream ID of the data source to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("sessions-delete", + Some(r##"Deletes a session specified by the given session ID."##), + "Details at http://byron.github.io/google-apis-rs/google_fitness1_cli/users_sessions-delete", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"Delete a session for the person identified. Use me to indicate the authenticated user. Only me is supported at this time."##), + Some(true), + Some(false)), + + (Some(r##"session-id"##), + None, + Some(r##"The ID of the session to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("sessions-list", + Some(r##"Lists sessions previously created."##), + "Details at http://byron.github.io/google-apis-rs/google_fitness1_cli/users_sessions-list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"List sessions for the person identified. Use me to indicate the authenticated user. Only me is supported at this time."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("sessions-update", + Some(r##"Updates or insert a given session."##), + "Details at http://byron.github.io/google-apis-rs/google_fitness1_cli/users_sessions-update", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"Create sessions for the person identified. Use me to indicate the authenticated user. Only me is supported at this time."##), + Some(true), + Some(false)), + + (Some(r##"session-id"##), + None, + Some(r##"The ID of the session to be created."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("fitness1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150326") + .about("Google Fit API") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_fitness1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/fitness1/Cargo.toml b/gen/fitness1/Cargo.toml index 80e28a822b..ba3e740b94 100644 --- a/gen/fitness1/Cargo.toml +++ b/gen/fitness1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-fitness1" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with fitness (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/fitness1" @@ -15,9 +15,10 @@ keywords = ["fitness", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/fitness1/README.md b/gen/fitness1/README.md index c261e229c4..e4f4a5675d 100644 --- a/gen/fitness1/README.md +++ b/gen/fitness1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-fitness1` library allows access to all features of the *Google fitness* service. -This documentation was generated from *fitness* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *fitness:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *fitness* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *fitness:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *fitness* *v1* API can be found at the [official documentation site](https://developers.google.com/fit/rest/). @@ -167,7 +167,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_fitness1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_fitness1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/fitness1/src/cmn.rs b/gen/fitness1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/fitness1/src/cmn.rs +++ b/gen/fitness1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/fitness1/src/lib.rs b/gen/fitness1/src/lib.rs index 572e097076..ab8bb20ce9 100644 --- a/gen/fitness1/src/lib.rs +++ b/gen/fitness1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *fitness* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *fitness:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *fitness* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *fitness:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *fitness* *v1* API can be found at the //! [official documentation site](https://developers.google.com/fit/rest/). @@ -168,7 +168,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -177,7 +177,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -193,6 +192,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -335,7 +335,7 @@ impl<'a, C, A> Fitness<C, A> Fitness { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -344,7 +344,7 @@ impl<'a, C, A> Fitness<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1082,7 +1082,7 @@ impl<'a, C, A> UserDataSourceDeleteCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1104,7 +1104,7 @@ impl<'a, C, A> UserDataSourceDeleteCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1345,7 +1345,7 @@ impl<'a, C, A> UserDataSourceDatasetGetCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1367,7 +1367,7 @@ impl<'a, C, A> UserDataSourceDatasetGetCall<'a, C, A> where C: BorrowMut<hyper:: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1570,6 +1570,7 @@ impl<'a, C, A> UserDataSourceCreateCall<'a, C, A> where C: BorrowMut<hyper::Clie /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, DataSource)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1625,11 +1626,20 @@ impl<'a, C, A> UserDataSourceCreateCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1652,7 +1662,7 @@ impl<'a, C, A> UserDataSourceCreateCall<'a, C, A> where C: BorrowMut<hyper::Clie request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1894,7 +1904,7 @@ impl<'a, C, A> UserDataSourceDatasetDeleteCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1916,7 +1926,7 @@ impl<'a, C, A> UserDataSourceDatasetDeleteCall<'a, C, A> where C: BorrowMut<hype access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2113,6 +2123,7 @@ impl<'a, C, A> UserDataSourceDatasetPatchCall<'a, C, A> where C: BorrowMut<hyper /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Dataset)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2173,11 +2184,20 @@ impl<'a, C, A> UserDataSourceDatasetPatchCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2200,7 +2220,7 @@ impl<'a, C, A> UserDataSourceDatasetPatchCall<'a, C, A> where C: BorrowMut<hyper request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2462,7 +2482,7 @@ impl<'a, C, A> UserSessionDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2484,7 +2504,7 @@ impl<'a, C, A> UserSessionDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2710,7 +2730,7 @@ impl<'a, C, A> UserDataSourceGetCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2732,7 +2752,7 @@ impl<'a, C, A> UserDataSourceGetCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2914,6 +2934,7 @@ impl<'a, C, A> UserDataSourceUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clie /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, DataSource)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2970,11 +2991,20 @@ impl<'a, C, A> UserDataSourceUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2997,7 +3027,7 @@ impl<'a, C, A> UserDataSourceUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clie request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3256,7 +3286,7 @@ impl<'a, C, A> UserSessionListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3278,7 +3308,7 @@ impl<'a, C, A> UserSessionListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3478,6 +3508,7 @@ impl<'a, C, A> UserSessionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client> /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Session)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3537,11 +3568,20 @@ impl<'a, C, A> UserSessionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3564,7 +3604,7 @@ impl<'a, C, A> UserSessionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client> request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3765,6 +3805,7 @@ impl<'a, C, A> UserDataSourcePatchCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, DataSource)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3821,11 +3862,20 @@ impl<'a, C, A> UserDataSourcePatchCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3848,7 +3898,7 @@ impl<'a, C, A> UserDataSourcePatchCall<'a, C, A> where C: BorrowMut<hyper::Clien request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4096,7 +4146,7 @@ impl<'a, C, A> UserDataSourceListCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4118,7 +4168,7 @@ impl<'a, C, A> UserDataSourceListCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/freebase1-cli/Cargo.toml b/gen/freebase1-cli/Cargo.toml index 56b23b42cb..81bebaedd2 100644 --- a/gen/freebase1-cli/Cargo.toml +++ b/gen/freebase1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-freebase1-cli" -version = "0.1.0+20150330" +version = "0.2.0+20150330" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with freebase (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/freebase1-cli" @@ -17,15 +17,14 @@ keywords = ["freebase", "google", "cli"] name = "freebase1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-freebase1] path = "../freebase1" diff --git a/gen/freebase1-cli/README.md b/gen/freebase1-cli/README.md index c62bbc4c41..1e09f92f62 100644 --- a/gen/freebase1-cli/README.md +++ b/gen/freebase1-cli/README.md @@ -10,18 +10,20 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *freebase* API can be found at the +[official documentation site](https://developers.google.com/freebase/). + # Usage -This documentation was generated from the *freebase* API at revision *20150330*. The CLI is at version *0.1.0*. +This documentation was generated from the *freebase* API at revision *20150330*. The CLI is at version *0.2.0*. ```bash - freebase1 [options] methods reconcile [-p <v>...] [-o <out>] - freebase1 [options] methods search [-p <v>...] [-o <out>] +freebase1 [options] + methods + reconcile [-p <v>]... [-o <out>] + search [-p <v>]... [-o <out>] freebase1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_freebase1_cli/index.html - Configuration: --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/freebase1-cli/mkdocs.yml b/gen/freebase1-cli/mkdocs.yml index 6fe8675c47..9df1ebff32 100644 --- a/gen/freebase1-cli/mkdocs.yml +++ b/gen/freebase1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: freebase v0.1.0+20150330 +site_name: freebase v0.2.0+20150330 site_url: http://byron.github.io/google-apis-rs/google-freebase1-cli site_description: Write integrating applications with bcore diff --git a/gen/freebase1-cli/src/cmn.rs b/gen/freebase1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/freebase1-cli/src/cmn.rs +++ b/gen/freebase1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/freebase1-cli/src/main.rs b/gen/freebase1-cli/src/main.rs index 3d422da62b..da0e0a2cff 100644 --- a/gen/freebase1-cli/src/main.rs +++ b/gen/freebase1-cli/src/main.rs @@ -2,64 +2,53 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_freebase1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - freebase1 [options] methods reconcile [-p <v>...] [-o <out>] - freebase1 [options] methods search [-p <v>...] [-o <out>] - freebase1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_freebase1_cli/index.html - -Configuration: - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Freebase<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _methods_reconcile(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _methods_reconcile(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.methods().reconcile(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "prop" => { @@ -80,48 +69,52 @@ impl Engine { "confidence" => { call = call.confidence(arg_from_str(value.unwrap_or("0.0"), err, "confidence", "number")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["lang", "kind", "name", "confidence", "prop", "limit"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _methods_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _methods_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut download_mode = false; let mut call = self.hub.methods().search(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "without" => { @@ -193,78 +186,90 @@ impl Engine { "as-of-time" => { call = call.as_of_time(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["domain", "help", "query", "stemmed", "cursor", "prefixed", "exact", "mid", "encode", "type", "as-of-time", "scoring", "format", "spell", "with", "lang", "indent", "filter", "callback", "without", "limit", "output", "mql-output"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { if !download_mode { } else { io::copy(&mut response, &mut ostream).unwrap(); } - None + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_methods { - if self.opt.cmd_reconcile { - call_result = self._methods_reconcile(dry_run, &mut err); - } else if self.opt.cmd_search { - call_result = self._methods_search(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("methods", Some(opt)) => { + match opt.subcommand() { + ("reconcile", Some(opt)) => { + call_result = self._methods_reconcile(opt, dry_run, &mut err); + }, + ("search", Some(opt)) => { + call_result = self._methods_search(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("methods".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -277,7 +282,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -290,7 +295,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -300,37 +305,153 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Freebase::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("methods", "methods: 'reconcile' and 'search'", vec![ + ("reconcile", + Some(r##"Reconcile entities to Freebase open data."##), + "Details at http://byron.github.io/google-apis-rs/google_freebase1_cli/methods_reconcile", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("search", + Some(r##"Search Freebase open data."##), + "Details at http://byron.github.io/google-apis-rs/google_freebase1_cli/methods_search", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("freebase1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150330") + .about("Find Freebase entities using textual queries and other constraints.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_freebase1_cli") + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/freebase1/Cargo.toml b/gen/freebase1/Cargo.toml index 3ac5e1ce6c..b25aaf62bd 100644 --- a/gen/freebase1/Cargo.toml +++ b/gen/freebase1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-freebase1" -version = "0.1.6+20150330" +version = "0.1.7+20150330" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with freebase (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/freebase1" @@ -15,9 +15,10 @@ keywords = ["freebase", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/freebase1/README.md b/gen/freebase1/README.md index 03e190d8c3..1b9ea928b9 100644 --- a/gen/freebase1/README.md +++ b/gen/freebase1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-freebase1` library allows access to all features of the *Google freebase* service. -This documentation was generated from *freebase* crate version *0.1.6+20150330*, where *20150330* is the exact revision of the *freebase:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *freebase* crate version *0.1.7+20150330*, where *20150330* is the exact revision of the *freebase:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *freebase* *v1* API can be found at the [official documentation site](https://developers.google.com/freebase/). @@ -167,7 +167,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_freebase1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_freebase1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/freebase1/src/cmn.rs b/gen/freebase1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/freebase1/src/cmn.rs +++ b/gen/freebase1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/freebase1/src/lib.rs b/gen/freebase1/src/lib.rs index 06a0342cad..ae90b33489 100644 --- a/gen/freebase1/src/lib.rs +++ b/gen/freebase1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *freebase* crate version *0.1.6+20150330*, where *20150330* is the exact revision of the *freebase:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *freebase* crate version *0.1.7+20150330*, where *20150330* is the exact revision of the *freebase:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *freebase* *v1* API can be found at the //! [official documentation site](https://developers.google.com/freebase/). @@ -168,7 +168,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -177,7 +177,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -193,6 +192,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -293,7 +293,7 @@ impl<'a, C, A> Freebase<C, A> Freebase { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -302,7 +302,7 @@ impl<'a, C, A> Freebase<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -641,7 +641,7 @@ impl<'a, C, A> MethodReconcileCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -649,7 +649,7 @@ impl<'a, C, A> MethodReconcileCall<'a, C, A> where C: BorrowMut<hyper::Client>, loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -1012,7 +1012,7 @@ impl<'a, C, A> MethodSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1020,7 +1020,7 @@ impl<'a, C, A> MethodSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); diff --git a/gen/freebase1_sandbox-cli/Cargo.toml b/gen/freebase1_sandbox-cli/Cargo.toml index 07e768e8d9..2242f677e2 100644 --- a/gen/freebase1_sandbox-cli/Cargo.toml +++ b/gen/freebase1_sandbox-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-freebase1_sandbox-cli" -version = "0.1.0+20150330" +version = "0.2.0+20150330" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with freebase (protocol v1sandbox)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/freebase1_sandbox-cli" @@ -17,15 +17,14 @@ keywords = ["freebase", "google", "cli"] name = "freebase1-sandbox" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-freebase1_sandbox] path = "../freebase1_sandbox" diff --git a/gen/freebase1_sandbox-cli/README.md b/gen/freebase1_sandbox-cli/README.md index 795a389cca..9f37605885 100644 --- a/gen/freebase1_sandbox-cli/README.md +++ b/gen/freebase1_sandbox-cli/README.md @@ -10,18 +10,20 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *freebase* API can be found at the +[official documentation site](https://developers.google.com/freebase/). + # Usage -This documentation was generated from the *freebase* API at revision *20150330*. The CLI is at version *0.1.0*. +This documentation was generated from the *freebase* API at revision *20150330*. The CLI is at version *0.2.0*. ```bash - freebase1-sandbox [options] methods reconcile [-p <v>...] [-o <out>] - freebase1-sandbox [options] methods search [-p <v>...] [-o <out>] +freebase1-sandbox [options] + methods + reconcile [-p <v>]... [-o <out>] + search [-p <v>]... [-o <out>] freebase1-sandbox --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_freebase1_sandbox_cli/index.html - Configuration: --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/freebase1_sandbox-cli/mkdocs.yml b/gen/freebase1_sandbox-cli/mkdocs.yml index f5c171c990..1343a84680 100644 --- a/gen/freebase1_sandbox-cli/mkdocs.yml +++ b/gen/freebase1_sandbox-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: freebase v0.1.0+20150330 +site_name: freebase v0.2.0+20150330 site_url: http://byron.github.io/google-apis-rs/google-freebase1_sandbox-cli site_description: Write integrating applications with bcore diff --git a/gen/freebase1_sandbox-cli/src/cmn.rs b/gen/freebase1_sandbox-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/freebase1_sandbox-cli/src/cmn.rs +++ b/gen/freebase1_sandbox-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/freebase1_sandbox-cli/src/main.rs b/gen/freebase1_sandbox-cli/src/main.rs index 5ae200e1eb..1d6902f250 100644 --- a/gen/freebase1_sandbox-cli/src/main.rs +++ b/gen/freebase1_sandbox-cli/src/main.rs @@ -2,64 +2,53 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_freebase1_sandbox as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - freebase1-sandbox [options] methods reconcile [-p <v>...] [-o <out>] - freebase1-sandbox [options] methods search [-p <v>...] [-o <out>] - freebase1-sandbox --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_freebase1_sandbox_cli/index.html - -Configuration: - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Freebase<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _methods_reconcile(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _methods_reconcile(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.methods().reconcile(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "prop" => { @@ -80,48 +69,52 @@ impl Engine { "confidence" => { call = call.confidence(arg_from_str(value.unwrap_or("0.0"), err, "confidence", "number")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["lang", "kind", "name", "confidence", "prop", "limit"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _methods_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _methods_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut download_mode = false; let mut call = self.hub.methods().search(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "without" => { @@ -193,78 +186,90 @@ impl Engine { "as-of-time" => { call = call.as_of_time(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["domain", "help", "query", "stemmed", "cursor", "prefixed", "exact", "mid", "encode", "type", "as-of-time", "scoring", "format", "spell", "with", "lang", "indent", "filter", "callback", "without", "limit", "output", "mql-output"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { if !download_mode { } else { io::copy(&mut response, &mut ostream).unwrap(); } - None + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_methods { - if self.opt.cmd_reconcile { - call_result = self._methods_reconcile(dry_run, &mut err); - } else if self.opt.cmd_search { - call_result = self._methods_search(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("methods", Some(opt)) => { + match opt.subcommand() { + ("reconcile", Some(opt)) => { + call_result = self._methods_reconcile(opt, dry_run, &mut err); + }, + ("search", Some(opt)) => { + call_result = self._methods_search(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("methods".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -277,7 +282,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -290,7 +295,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -300,37 +305,153 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Freebase::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("methods", "methods: 'reconcile' and 'search'", vec![ + ("reconcile", + Some(r##"Reconcile entities to Freebase open data."##), + "Details at http://byron.github.io/google-apis-rs/google_freebase1_sandbox_cli/methods_reconcile", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("search", + Some(r##"Search Freebase open data."##), + "Details at http://byron.github.io/google-apis-rs/google_freebase1_sandbox_cli/methods_search", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("freebase1-sandbox") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150330") + .about("Find Freebase entities using textual queries and other constraints.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_freebase1_sandbox_cli") + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/freebase1_sandbox/Cargo.toml b/gen/freebase1_sandbox/Cargo.toml index f17faa8d5b..891bb62e01 100644 --- a/gen/freebase1_sandbox/Cargo.toml +++ b/gen/freebase1_sandbox/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-freebase1_sandbox" -version = "0.1.6+20150330" +version = "0.1.7+20150330" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with freebase (protocol v1sandbox)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/freebase1_sandbox" @@ -15,9 +15,10 @@ keywords = ["freebase", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/freebase1_sandbox/README.md b/gen/freebase1_sandbox/README.md index 602c78509b..632805a306 100644 --- a/gen/freebase1_sandbox/README.md +++ b/gen/freebase1_sandbox/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-freebase1_sandbox` library allows access to all features of the *Google freebase* service. -This documentation was generated from *freebase* crate version *0.1.6+20150330*, where *20150330* is the exact revision of the *freebase:v1sandbox* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *freebase* crate version *0.1.7+20150330*, where *20150330* is the exact revision of the *freebase:v1sandbox* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *freebase* *v1_sandbox* API can be found at the [official documentation site](https://developers.google.com/freebase/). @@ -167,7 +167,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_freebase1_sandbox/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_freebase1_sandbox/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/freebase1_sandbox/src/cmn.rs b/gen/freebase1_sandbox/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/freebase1_sandbox/src/cmn.rs +++ b/gen/freebase1_sandbox/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/freebase1_sandbox/src/lib.rs b/gen/freebase1_sandbox/src/lib.rs index 9026025553..a279e84234 100644 --- a/gen/freebase1_sandbox/src/lib.rs +++ b/gen/freebase1_sandbox/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *freebase* crate version *0.1.6+20150330*, where *20150330* is the exact revision of the *freebase:v1sandbox* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *freebase* crate version *0.1.7+20150330*, where *20150330* is the exact revision of the *freebase:v1sandbox* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *freebase* *v1_sandbox* API can be found at the //! [official documentation site](https://developers.google.com/freebase/). @@ -168,7 +168,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -177,7 +177,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -193,6 +192,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -293,7 +293,7 @@ impl<'a, C, A> Freebase<C, A> Freebase { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -302,7 +302,7 @@ impl<'a, C, A> Freebase<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -641,7 +641,7 @@ impl<'a, C, A> MethodReconcileCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -649,7 +649,7 @@ impl<'a, C, A> MethodReconcileCall<'a, C, A> where C: BorrowMut<hyper::Client>, loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -1012,7 +1012,7 @@ impl<'a, C, A> MethodSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1020,7 +1020,7 @@ impl<'a, C, A> MethodSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); diff --git a/gen/fusiontables2-cli/Cargo.toml b/gen/fusiontables2-cli/Cargo.toml index 030115d1c7..a55cebd81d 100644 --- a/gen/fusiontables2-cli/Cargo.toml +++ b/gen/fusiontables2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-fusiontables2-cli" -version = "0.1.0+20150326" +version = "0.2.0+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with fusiontables (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/fusiontables2-cli" @@ -17,15 +17,14 @@ keywords = ["fusiontables", "google", "cli"] name = "fusiontables2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-fusiontables2] path = "../fusiontables2" diff --git a/gen/fusiontables2-cli/README.md b/gen/fusiontables2-cli/README.md index 2405e74891..dd8ffbd6eb 100644 --- a/gen/fusiontables2-cli/README.md +++ b/gen/fusiontables2-cli/README.md @@ -10,53 +10,60 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *fusiontables* API can be found at the +[official documentation site](https://developers.google.com/fusiontables). + # Usage -This documentation was generated from the *fusiontables* API at revision *20150326*. The CLI is at version *0.1.0*. +This documentation was generated from the *fusiontables* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - fusiontables2 [options] column delete <table-id> <column-id> [-p <v>...] - fusiontables2 [options] column get <table-id> <column-id> [-p <v>...] [-o <out>] - fusiontables2 [options] column insert <table-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] column list <table-id> [-p <v>...] [-o <out>] - fusiontables2 [options] column patch <table-id> <column-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] column update <table-id> <column-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] query sql <sql> [-p <v>...] [-o <out>] - fusiontables2 [options] query sql-get <sql> [-p <v>...] [-o <out>] - fusiontables2 [options] style delete <table-id> <style-id> [-p <v>...] - fusiontables2 [options] style get <table-id> <style-id> [-p <v>...] [-o <out>] - fusiontables2 [options] style insert <table-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] style list <table-id> [-p <v>...] [-o <out>] - fusiontables2 [options] style patch <table-id> <style-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] style update <table-id> <style-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] table copy <table-id> [-p <v>...] [-o <out>] - fusiontables2 [options] table delete <table-id> [-p <v>...] - fusiontables2 [options] table get <table-id> [-p <v>...] [-o <out>] - fusiontables2 [options] table import-rows <table-id> -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - fusiontables2 [options] table import-table <name> -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - fusiontables2 [options] table insert -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] table list [-p <v>...] [-o <out>] - fusiontables2 [options] table patch <table-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] table replace-rows <table-id> -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - fusiontables2 [options] table update <table-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] task delete <table-id> <task-id> [-p <v>...] - fusiontables2 [options] task get <table-id> <task-id> [-p <v>...] [-o <out>] - fusiontables2 [options] task list <table-id> [-p <v>...] [-o <out>] - fusiontables2 [options] template delete <table-id> <template-id> [-p <v>...] - fusiontables2 [options] template get <table-id> <template-id> [-p <v>...] [-o <out>] - fusiontables2 [options] template insert <table-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] template list <table-id> [-p <v>...] [-o <out>] - fusiontables2 [options] template patch <table-id> <template-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] template update <table-id> <template-id> -r <kv>... [-p <v>...] [-o <out>] +fusiontables2 [options] + column + delete <table-id> <column-id> [-p <v>]... + get <table-id> <column-id> [-p <v>]... [-o <out>] + insert <table-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <table-id> [-p <v>]... [-o <out>] + patch <table-id> <column-id> (-r <kv>)... [-p <v>]... [-o <out>] + update <table-id> <column-id> (-r <kv>)... [-p <v>]... [-o <out>] + query + sql <sql> [-p <v>]... [-o <out>] + sql-get <sql> [-p <v>]... [-o <out>] + style + delete <table-id> <style-id> [-p <v>]... + get <table-id> <style-id> [-p <v>]... [-o <out>] + insert <table-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <table-id> [-p <v>]... [-o <out>] + patch <table-id> <style-id> (-r <kv>)... [-p <v>]... [-o <out>] + update <table-id> <style-id> (-r <kv>)... [-p <v>]... [-o <out>] + table + copy <table-id> [-p <v>]... [-o <out>] + delete <table-id> [-p <v>]... + get <table-id> [-p <v>]... [-o <out>] + import-rows <table-id> (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + import-table <name> (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + insert (-r <kv>)... [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + patch <table-id> (-r <kv>)... [-p <v>]... [-o <out>] + replace-rows <table-id> (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + update <table-id> (-r <kv>)... [-p <v>]... [-o <out>] + task + delete <table-id> <task-id> [-p <v>]... + get <table-id> <task-id> [-p <v>]... [-o <out>] + list <table-id> [-p <v>]... [-o <out>] + template + delete <table-id> <template-id> [-p <v>]... + get <table-id> <template-id> [-p <v>]... [-o <out>] + insert <table-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <table-id> [-p <v>]... [-o <out>] + patch <table-id> <template-id> (-r <kv>)... [-p <v>]... [-o <out>] + update <table-id> <template-id> (-r <kv>)... [-p <v>]... [-o <out>] fusiontables2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_fusiontables2_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/fusiontables2-cli/mkdocs.yml b/gen/fusiontables2-cli/mkdocs.yml index cdbbbe41f8..cb52675e73 100644 --- a/gen/fusiontables2-cli/mkdocs.yml +++ b/gen/fusiontables2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: fusiontables v0.1.0+20150326 +site_name: fusiontables v0.2.0+20150326 site_url: http://byron.github.io/google-apis-rs/google-fusiontables2-cli site_description: Write integrating applications with bcore diff --git a/gen/fusiontables2-cli/src/cmn.rs b/gen/fusiontables2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/fusiontables2-cli/src/cmn.rs +++ b/gen/fusiontables2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/fusiontables2-cli/src/main.rs b/gen/fusiontables2-cli/src/main.rs index 1241920fda..9c44bea36f 100644 --- a/gen/fusiontables2-cli/src/main.rs +++ b/gen/fusiontables2-cli/src/main.rs @@ -2,191 +2,148 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_fusiontables2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - fusiontables2 [options] column delete <table-id> <column-id> [-p <v>...] - fusiontables2 [options] column get <table-id> <column-id> [-p <v>...] [-o <out>] - fusiontables2 [options] column insert <table-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] column list <table-id> [-p <v>...] [-o <out>] - fusiontables2 [options] column patch <table-id> <column-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] column update <table-id> <column-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] query sql <sql> [-p <v>...] [-o <out>] - fusiontables2 [options] query sql-get <sql> [-p <v>...] [-o <out>] - fusiontables2 [options] style delete <table-id> <style-id> [-p <v>...] - fusiontables2 [options] style get <table-id> <style-id> [-p <v>...] [-o <out>] - fusiontables2 [options] style insert <table-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] style list <table-id> [-p <v>...] [-o <out>] - fusiontables2 [options] style patch <table-id> <style-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] style update <table-id> <style-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] table copy <table-id> [-p <v>...] [-o <out>] - fusiontables2 [options] table delete <table-id> [-p <v>...] - fusiontables2 [options] table get <table-id> [-p <v>...] [-o <out>] - fusiontables2 [options] table import-rows <table-id> -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - fusiontables2 [options] table import-table <name> -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - fusiontables2 [options] table insert -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] table list [-p <v>...] [-o <out>] - fusiontables2 [options] table patch <table-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] table replace-rows <table-id> -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - fusiontables2 [options] table update <table-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] task delete <table-id> <task-id> [-p <v>...] - fusiontables2 [options] task get <table-id> <task-id> [-p <v>...] [-o <out>] - fusiontables2 [options] task list <table-id> [-p <v>...] [-o <out>] - fusiontables2 [options] template delete <table-id> <template-id> [-p <v>...] - fusiontables2 [options] template get <table-id> <template-id> [-p <v>...] [-o <out>] - fusiontables2 [options] template insert <table-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] template list <table-id> [-p <v>...] [-o <out>] - fusiontables2 [options] template patch <table-id> <template-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 [options] template update <table-id> <template-id> -r <kv>... [-p <v>...] [-o <out>] - fusiontables2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_fusiontables2_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Fusiontables<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _column_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.column().delete(&self.opt.arg_table_id, &self.opt.arg_column_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _column_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.column().delete(opt.value_of("table-id").unwrap_or(""), opt.value_of("column-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _column_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.column().get(&self.opt.arg_table_id, &self.opt.arg_column_id); - for parg in self.opt.arg_v.iter() { + fn _column_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.column().get(opt.value_of("table-id").unwrap_or(""), opt.value_of("column-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _column_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _column_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Column::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -259,58 +216,63 @@ impl Engine { request.column_id = Some(arg_from_str(value.unwrap_or("-0"), err, "column-id", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["base-column", "column-id", "column-json-schema", "column-properties-json", "description", "format-pattern", "graph-predicate", "kind", "name", "table-index", "type", "valid-values", "validate-data"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.column().insert(request, &self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.column().insert(request, opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _column_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.column().list(&self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + fn _column_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.column().list(opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -319,52 +281,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _column_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _column_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Column::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -437,60 +403,65 @@ impl Engine { request.column_id = Some(arg_from_str(value.unwrap_or("-0"), err, "column-id", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["base-column", "column-id", "column-json-schema", "column-properties-json", "description", "format-pattern", "graph-predicate", "kind", "name", "table-index", "type", "valid-values", "validate-data"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.column().patch(request, &self.opt.arg_table_id, &self.opt.arg_column_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.column().patch(request, opt.value_of("table-id").unwrap_or(""), opt.value_of("column-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _column_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _column_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Column::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -563,59 +534,64 @@ impl Engine { request.column_id = Some(arg_from_str(value.unwrap_or("-0"), err, "column-id", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["base-column", "column-id", "column-json-schema", "column-properties-json", "description", "format-pattern", "graph-predicate", "kind", "name", "table-index", "type", "valid-values", "validate-data"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.column().update(request, &self.opt.arg_table_id, &self.opt.arg_column_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.column().update(request, opt.value_of("table-id").unwrap_or(""), opt.value_of("column-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _query_sql(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _query_sql(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut download_mode = false; - let mut call = self.hub.query().sql(&self.opt.arg_sql); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.query().sql(opt.value_of("sql").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "typed" => { @@ -624,58 +600,62 @@ impl Engine { "hdrs" => { call = call.hdrs(arg_from_str(value.unwrap_or("false"), err, "hdrs", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["typed", "hdrs"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { if !download_mode { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); } else { io::copy(&mut response, &mut ostream).unwrap(); } - None + Ok(()) } } } } - fn _query_sql_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _query_sql_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut download_mode = false; - let mut call = self.hub.query().sql_get(&self.opt.arg_sql); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.query().sql_get(opt.value_of("sql").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "typed" => { @@ -684,151 +664,158 @@ impl Engine { "hdrs" => { call = call.hdrs(arg_from_str(value.unwrap_or("false"), err, "hdrs", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["typed", "hdrs"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { if !download_mode { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); } else { io::copy(&mut response, &mut ostream).unwrap(); } - None + Ok(()) } } } } - fn _style_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let style_id: i32 = arg_from_str(&self.opt.arg_style_id, err, "<style-id>", "integer"); - let mut call = self.hub.style().delete(&self.opt.arg_table_id, style_id); - for parg in self.opt.arg_v.iter() { + fn _style_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let style_id: i32 = arg_from_str(&opt.value_of("style-id").unwrap_or(""), err, "<style-id>", "integer"); + let mut call = self.hub.style().delete(opt.value_of("table-id").unwrap_or(""), style_id); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _style_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let style_id: i32 = arg_from_str(&self.opt.arg_style_id, err, "<style-id>", "integer"); - let mut call = self.hub.style().get(&self.opt.arg_table_id, style_id); - for parg in self.opt.arg_v.iter() { + fn _style_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let style_id: i32 = arg_from_str(&opt.value_of("style-id").unwrap_or(""), err, "<style-id>", "integer"); + let mut call = self.hub.style().get(opt.value_of("table-id").unwrap_or(""), style_id); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _style_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _style_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::StyleSetting::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1094,58 +1081,63 @@ impl Engine { request.style_id = Some(arg_from_str(value.unwrap_or("-0"), err, "style-id", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["column-name", "fill-color", "fill-color-styler", "fill-opacity", "gradient", "icon-name", "icon-styler", "kind", "marker-options", "max", "min", "name", "polygon-options", "polyline-options", "stroke-color", "stroke-color-styler", "stroke-opacity", "stroke-weight", "stroke-weight-styler", "style-id", "table-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.style().insert(request, &self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.style().insert(request, opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _style_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.style().list(&self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + fn _style_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.style().list(opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1154,52 +1146,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _style_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _style_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::StyleSetting::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1465,61 +1461,66 @@ impl Engine { request.style_id = Some(arg_from_str(value.unwrap_or("-0"), err, "style-id", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["column-name", "fill-color", "fill-color-styler", "fill-opacity", "gradient", "icon-name", "icon-styler", "kind", "marker-options", "max", "min", "name", "polygon-options", "polyline-options", "stroke-color", "stroke-color-styler", "stroke-opacity", "stroke-weight", "stroke-weight-styler", "style-id", "table-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let style_id: i32 = arg_from_str(&self.opt.arg_style_id, err, "<style-id>", "integer"); - let mut call = self.hub.style().patch(request, &self.opt.arg_table_id, style_id); - for parg in self.opt.arg_v.iter() { + let style_id: i32 = arg_from_str(&opt.value_of("style-id").unwrap_or(""), err, "<style-id>", "integer"); + let mut call = self.hub.style().patch(request, opt.value_of("table-id").unwrap_or(""), style_id); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _style_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _style_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::StyleSetting::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1785,198 +1786,210 @@ impl Engine { request.style_id = Some(arg_from_str(value.unwrap_or("-0"), err, "style-id", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["column-name", "fill-color", "fill-color-styler", "fill-opacity", "gradient", "icon-name", "icon-styler", "kind", "marker-options", "max", "min", "name", "polygon-options", "polyline-options", "stroke-color", "stroke-color-styler", "stroke-opacity", "stroke-weight", "stroke-weight-styler", "style-id", "table-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let style_id: i32 = arg_from_str(&self.opt.arg_style_id, err, "<style-id>", "integer"); - let mut call = self.hub.style().update(request, &self.opt.arg_table_id, style_id); - for parg in self.opt.arg_v.iter() { + let style_id: i32 = arg_from_str(&opt.value_of("style-id").unwrap_or(""), err, "<style-id>", "integer"); + let mut call = self.hub.style().update(request, opt.value_of("table-id").unwrap_or(""), style_id); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _table_copy(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.table().copy(&self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + fn _table_copy(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.table().copy(opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "copy-presentation" => { call = call.copy_presentation(arg_from_str(value.unwrap_or("false"), err, "copy-presentation", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["copy-presentation"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _table_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.table().delete(&self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + fn _table_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.table().delete(opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _table_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.table().get(&self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + fn _table_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.table().get(opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _table_import_rows(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.table().import_rows(&self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + fn _table_import_rows(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.table().import_rows(opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-line" => { @@ -1994,60 +2007,58 @@ impl Engine { "delimiter" => { call = call.delimiter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["encoding", "end-line", "start-line", "delimiter", "is-strict"] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() - }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _table_import_table(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.table().import_table(&self.opt.arg_name); - for parg in self.opt.arg_v.iter() { + fn _table_import_table(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.table().import_table(opt.value_of("name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "encoding" => { @@ -2056,62 +2067,60 @@ impl Engine { "delimiter" => { call = call.delimiter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["delimiter", "encoding"] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() - }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _table_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _table_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Table::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2166,58 +2175,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attribution", "attribution-link", "base-table-ids", "column-properties-json-schema", "description", "is-exportable", "kind", "name", "sql", "table-id", "table-properties-json", "table-properties-json-schema"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.table().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _table_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _table_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.table().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2226,52 +2240,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _table_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _table_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Table::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2326,61 +2344,66 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attribution", "attribution-link", "base-table-ids", "column-properties-json-schema", "description", "is-exportable", "kind", "name", "sql", "table-id", "table-properties-json", "table-properties-json-schema"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.table().patch(request, &self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.table().patch(request, opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "replace-view-definition" => { call = call.replace_view_definition(arg_from_str(value.unwrap_or("false"), err, "replace-view-definition", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["replace-view-definition"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _table_replace_rows(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.table().replace_rows(&self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + fn _table_replace_rows(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.table().replace_rows(opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-line" => { @@ -2398,62 +2421,60 @@ impl Engine { "delimiter" => { call = call.delimiter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["encoding", "end-line", "start-line", "delimiter", "is-strict"] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() - }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _table_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _table_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Table::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2508,151 +2529,159 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attribution", "attribution-link", "base-table-ids", "column-properties-json-schema", "description", "is-exportable", "kind", "name", "sql", "table-id", "table-properties-json", "table-properties-json-schema"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.table().update(request, &self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.table().update(request, opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "replace-view-definition" => { call = call.replace_view_definition(arg_from_str(value.unwrap_or("false"), err, "replace-view-definition", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["replace-view-definition"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _task_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.task().delete(&self.opt.arg_table_id, &self.opt.arg_task_id); - for parg in self.opt.arg_v.iter() { + fn _task_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.task().delete(opt.value_of("table-id").unwrap_or(""), opt.value_of("task-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _task_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.task().get(&self.opt.arg_table_id, &self.opt.arg_task_id); - for parg in self.opt.arg_v.iter() { + fn _task_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.task().get(opt.value_of("table-id").unwrap_or(""), opt.value_of("task-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _task_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.task().list(&self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + fn _task_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.task().list(opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -2664,144 +2693,151 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "start-index", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _template_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let template_id: i32 = arg_from_str(&self.opt.arg_template_id, err, "<template-id>", "integer"); - let mut call = self.hub.template().delete(&self.opt.arg_table_id, template_id); - for parg in self.opt.arg_v.iter() { + fn _template_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let template_id: i32 = arg_from_str(&opt.value_of("template-id").unwrap_or(""), err, "<template-id>", "integer"); + let mut call = self.hub.template().delete(opt.value_of("table-id").unwrap_or(""), template_id); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _template_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let template_id: i32 = arg_from_str(&self.opt.arg_template_id, err, "<template-id>", "integer"); - let mut call = self.hub.template().get(&self.opt.arg_table_id, template_id); - for parg in self.opt.arg_v.iter() { + fn _template_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let template_id: i32 = arg_from_str(&opt.value_of("template-id").unwrap_or(""), err, "<template-id>", "integer"); + let mut call = self.hub.template().get(opt.value_of("table-id").unwrap_or(""), template_id); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _template_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _template_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Template::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2838,58 +2874,63 @@ impl Engine { request.template_id = Some(arg_from_str(value.unwrap_or("-0"), err, "template-id", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["automatic-column-names", "body", "kind", "name", "table-id", "template-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.template().insert(request, &self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.template().insert(request, opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _template_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.template().list(&self.opt.arg_table_id); - for parg in self.opt.arg_v.iter() { + fn _template_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.template().list(opt.value_of("table-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2898,52 +2939,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _template_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _template_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Template::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2980,61 +3025,66 @@ impl Engine { request.template_id = Some(arg_from_str(value.unwrap_or("-0"), err, "template-id", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["automatic-column-names", "body", "kind", "name", "table-id", "template-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let template_id: i32 = arg_from_str(&self.opt.arg_template_id, err, "<template-id>", "integer"); - let mut call = self.hub.template().patch(request, &self.opt.arg_table_id, template_id); - for parg in self.opt.arg_v.iter() { + let template_id: i32 = arg_from_str(&opt.value_of("template-id").unwrap_or(""), err, "<template-id>", "integer"); + let mut call = self.hub.template().patch(request, opt.value_of("table-id").unwrap_or(""), template_id); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _template_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _template_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Template::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3071,171 +3121,232 @@ impl Engine { request.template_id = Some(arg_from_str(value.unwrap_or("-0"), err, "template-id", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["automatic-column-names", "body", "kind", "name", "table-id", "template-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let template_id: i32 = arg_from_str(&self.opt.arg_template_id, err, "<template-id>", "integer"); - let mut call = self.hub.template().update(request, &self.opt.arg_table_id, template_id); - for parg in self.opt.arg_v.iter() { + let template_id: i32 = arg_from_str(&opt.value_of("template-id").unwrap_or(""), err, "<template-id>", "integer"); + let mut call = self.hub.template().update(request, opt.value_of("table-id").unwrap_or(""), template_id); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_column { - if self.opt.cmd_delete { - call_result = self._column_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._column_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._column_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._column_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._column_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._column_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("column", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._column_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._column_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._column_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._column_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._column_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._column_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("column".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("query", Some(opt)) => { + match opt.subcommand() { + ("sql", Some(opt)) => { + call_result = self._query_sql(opt, dry_run, &mut err); + }, + ("sql-get", Some(opt)) => { + call_result = self._query_sql_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("query".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("style", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._style_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._style_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._style_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._style_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._style_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._style_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("style".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("table", Some(opt)) => { + match opt.subcommand() { + ("copy", Some(opt)) => { + call_result = self._table_copy(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._table_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._table_get(opt, dry_run, &mut err); + }, + ("import-rows", Some(opt)) => { + call_result = self._table_import_rows(opt, dry_run, &mut err); + }, + ("import-table", Some(opt)) => { + call_result = self._table_import_table(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._table_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._table_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._table_patch(opt, dry_run, &mut err); + }, + ("replace-rows", Some(opt)) => { + call_result = self._table_replace_rows(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._table_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("table".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("task", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._task_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._task_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._task_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("task".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("template", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._template_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._template_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._template_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._template_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._template_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._template_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("template".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_query { - if self.opt.cmd_sql { - call_result = self._query_sql(dry_run, &mut err); - } else if self.opt.cmd_sql_get { - call_result = self._query_sql_get(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_style { - if self.opt.cmd_delete { - call_result = self._style_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._style_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._style_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._style_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._style_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._style_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_table { - if self.opt.cmd_copy { - call_result = self._table_copy(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._table_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._table_get(dry_run, &mut err); - } else if self.opt.cmd_import_rows { - call_result = self._table_import_rows(dry_run, &mut err); - } else if self.opt.cmd_import_table { - call_result = self._table_import_table(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._table_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._table_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._table_patch(dry_run, &mut err); - } else if self.opt.cmd_replace_rows { - call_result = self._table_replace_rows(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._table_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_task { - if self.opt.cmd_delete { - call_result = self._task_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._task_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._task_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_template { - if self.opt.cmd_delete { - call_result = self._template_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._template_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._template_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._template_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._template_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._template_update(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -3248,7 +3359,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -3261,7 +3372,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -3271,37 +3382,1031 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Fusiontables::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let upload_value_names = ["mode", "file"]; + let arg_data = [ + ("column", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes the specified column."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/column_delete", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table from which the column is being deleted."##), + Some(true), + Some(false)), + + (Some(r##"column-id"##), + None, + Some(r##"Name or identifier for the column being deleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves a specific column by its ID."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/column_get", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table to which the column belongs."##), + Some(true), + Some(false)), + + (Some(r##"column-id"##), + None, + Some(r##"Name or identifier for the column that is being requested."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Adds a new column to the table."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/column_insert", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table for which a new column is being added."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of columns."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/column_list", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table whose columns are being listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates the name or type of an existing column. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/column_patch", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table for which the column is being updated."##), + Some(true), + Some(false)), + + (Some(r##"column-id"##), + None, + Some(r##"Name or identifier for the column that is being updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates the name or type of an existing column."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/column_update", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table for which the column is being updated."##), + Some(true), + Some(false)), + + (Some(r##"column-id"##), + None, + Some(r##"Name or identifier for the column that is being updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("query", "methods: 'sql' and 'sql-get'", vec![ + ("sql", + Some(r##"Executes a Fusion Tables SQL statement, which can be any of + - SELECT + - INSERT + - UPDATE + - DELETE + - SHOW + - DESCRIBE + - CREATE statement."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/query_sql", + vec![ + (Some(r##"sql"##), + None, + Some(r##"A Fusion Tables SQL statement, which can be any of + - SELECT + - INSERT + - UPDATE + - DELETE + - SHOW + - DESCRIBE + - CREATE"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("sql-get", + Some(r##"Executes a SQL statement which can be any of + - SELECT + - SHOW + - DESCRIBE"##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/query_sql-get", + vec![ + (Some(r##"sql"##), + None, + Some(r##"A SQL statement which can be any of + - SELECT + - SHOW + - DESCRIBE"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("style", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes a style."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/style_delete", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table from which the style is being deleted"##), + Some(true), + Some(false)), + + (Some(r##"style-id"##), + None, + Some(r##"Identifier (within a table) for the style being deleted"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets a specific style."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/style_get", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table to which the requested style belongs"##), + Some(true), + Some(false)), + + (Some(r##"style-id"##), + None, + Some(r##"Identifier (integer) for a specific style in a table"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Adds a new style for the table."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/style_insert", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table for which a new style is being added"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of styles."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/style_list", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table whose styles are being listed"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing style. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/style_patch", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table whose style is being updated."##), + Some(true), + Some(false)), + + (Some(r##"style-id"##), + None, + Some(r##"Identifier (within a table) for the style being updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing style."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/style_update", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table whose style is being updated."##), + Some(true), + Some(false)), + + (Some(r##"style-id"##), + None, + Some(r##"Identifier (within a table) for the style being updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("table", "methods: 'copy', 'delete', 'get', 'import-rows', 'import-table', 'insert', 'list', 'patch', 'replace-rows' and 'update'", vec![ + ("copy", + Some(r##"Copies a table."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/table_copy", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"ID of the table that is being copied."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes a table."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/table_delete", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"ID of the table to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves a specific table by its ID."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/table_get", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Identifier for the table being requested."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("import-rows", + Some(r##"Imports more rows into a table."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/table_import-rows", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"The table into which new rows are being imported."##), + Some(true), + Some(false)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("import-table", + Some(r##"Imports a new table."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/table_import-table", + vec![ + (Some(r##"name"##), + None, + Some(r##"The name to be assigned to the new table."##), + Some(true), + Some(false)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new table."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/table_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of tables a user owns."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/table_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing table. Unless explicitly requested, only the name, description, and attribution will be updated. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/table_patch", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"ID of the table that is being updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("replace-rows", + Some(r##"Replaces rows of an existing table. Current rows remain visible until all replacement rows are ready."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/table_replace-rows", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table whose rows will be replaced."##), + Some(true), + Some(false)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing table. Unless explicitly requested, only the name, description, and attribution will be updated."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/table_update", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"ID of the table that is being updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("task", "methods: 'delete', 'get' and 'list'", vec![ + ("delete", + Some(r##"Deletes a specific task by its ID, unless that task has already started running."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/task_delete", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table from which the task is being deleted."##), + Some(true), + Some(false)), + + (Some(r##"task-id"##), + None, + Some(r##"The identifier of the task to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves a specific task by its ID."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/task_get", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table to which the task belongs."##), + Some(true), + Some(false)), + + (Some(r##"task-id"##), + None, + Some(r##"The identifier of the task to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of tasks."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/task_list", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table whose tasks are being listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("template", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes a template"##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/template_delete", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table from which the template is being deleted"##), + Some(true), + Some(false)), + + (Some(r##"template-id"##), + None, + Some(r##"Identifier for the template which is being deleted"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves a specific template by its id"##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/template_get", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table to which the template belongs"##), + Some(true), + Some(false)), + + (Some(r##"template-id"##), + None, + Some(r##"Identifier for the template that is being requested"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new template for the table."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/template_insert", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table for which a new template is being created"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of templates."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/template_list", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Identifier for the table whose templates are being requested"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing template. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/template_patch", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table to which the updated template belongs"##), + Some(true), + Some(false)), + + (Some(r##"template-id"##), + None, + Some(r##"Identifier for the template that is being updated"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing template"##), + "Details at http://byron.github.io/google-apis-rs/google_fusiontables2_cli/template_update", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"Table to which the updated template belongs"##), + Some(true), + Some(false)), + + (Some(r##"template-id"##), + None, + Some(r##"Identifier for the template that is being updated"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("fusiontables2") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150326") + .about("API for working with Fusion Tables data.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_fusiontables2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + if arg_name_str == "mode" { + arg = arg.number_of_values(2); + arg = arg.value_names(&upload_value_names); + + scmd = scmd.arg(Arg::with_name("mime") + .short("m") + .requires("mode") + .required(false) + .help("The file's mime time, like 'application/octet-stream'") + .takes_value(true)); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/fusiontables2/Cargo.toml b/gen/fusiontables2/Cargo.toml index 751e2a0e62..ac905c110f 100644 --- a/gen/fusiontables2/Cargo.toml +++ b/gen/fusiontables2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-fusiontables2" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with fusiontables (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/fusiontables2" @@ -15,9 +15,10 @@ keywords = ["fusiontables", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/fusiontables2/README.md b/gen/fusiontables2/README.md index 2f8e6de42a..998868df67 100644 --- a/gen/fusiontables2/README.md +++ b/gen/fusiontables2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-fusiontables2` library allows access to all features of the *Google fusiontables* service. -This documentation was generated from *fusiontables* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *fusiontables:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *fusiontables* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *fusiontables:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *fusiontables* *v2* API can be found at the [official documentation site](https://developers.google.com/fusiontables). @@ -186,7 +186,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_fusiontables2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_fusiontables2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/fusiontables2/src/cmn.rs b/gen/fusiontables2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/fusiontables2/src/cmn.rs +++ b/gen/fusiontables2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/fusiontables2/src/lib.rs b/gen/fusiontables2/src/lib.rs index 4c42e7efbe..dcd47a03e8 100644 --- a/gen/fusiontables2/src/lib.rs +++ b/gen/fusiontables2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *fusiontables* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *fusiontables:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *fusiontables* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *fusiontables:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *fusiontables* *v2* API can be found at the //! [official documentation site](https://developers.google.com/fusiontables). @@ -187,7 +187,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -196,7 +196,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -212,6 +211,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -335,7 +335,7 @@ impl<'a, C, A> Fusiontables<C, A> Fusiontables { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -359,7 +359,7 @@ impl<'a, C, A> Fusiontables<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1956,7 +1956,7 @@ impl<'a, C, A> StyleListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1978,7 +1978,7 @@ impl<'a, C, A> StyleListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2162,6 +2162,7 @@ impl<'a, C, A> StyleUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, StyleSetting)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2218,11 +2219,20 @@ impl<'a, C, A> StyleUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2245,7 +2255,7 @@ impl<'a, C, A> StyleUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2436,6 +2446,7 @@ impl<'a, C, A> StyleInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, StyleSetting)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2491,11 +2502,20 @@ impl<'a, C, A> StyleInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2518,7 +2538,7 @@ impl<'a, C, A> StyleInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2749,7 +2769,7 @@ impl<'a, C, A> StyleGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2771,7 +2791,7 @@ impl<'a, C, A> StyleGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2999,7 +3019,7 @@ impl<'a, C, A> StyleDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3021,7 +3041,7 @@ impl<'a, C, A> StyleDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3191,6 +3211,7 @@ impl<'a, C, A> StylePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, StyleSetting)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3247,11 +3268,20 @@ impl<'a, C, A> StylePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3274,7 +3304,7 @@ impl<'a, C, A> StylePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3528,7 +3558,7 @@ impl<'a, C, A> TaskListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3550,7 +3580,7 @@ impl<'a, C, A> TaskListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3789,7 +3819,7 @@ impl<'a, C, A> TaskDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3811,7 +3841,7 @@ impl<'a, C, A> TaskDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4030,7 +4060,7 @@ impl<'a, C, A> TaskGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4052,7 +4082,7 @@ impl<'a, C, A> TaskGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4231,6 +4261,7 @@ impl<'a, C, A> ColumnInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Column)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4286,11 +4317,20 @@ impl<'a, C, A> ColumnInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4313,7 +4353,7 @@ impl<'a, C, A> ColumnInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4495,6 +4535,7 @@ impl<'a, C, A> ColumnUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Column)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4551,11 +4592,20 @@ impl<'a, C, A> ColumnUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4578,7 +4628,7 @@ impl<'a, C, A> ColumnUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4827,7 +4877,7 @@ impl<'a, C, A> ColumnListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4849,7 +4899,7 @@ impl<'a, C, A> ColumnListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5033,6 +5083,7 @@ impl<'a, C, A> ColumnPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Column)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5089,11 +5140,20 @@ impl<'a, C, A> ColumnPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5116,7 +5176,7 @@ impl<'a, C, A> ColumnPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5356,7 +5416,7 @@ impl<'a, C, A> ColumnDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5378,7 +5438,7 @@ impl<'a, C, A> ColumnDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5597,7 +5657,7 @@ impl<'a, C, A> ColumnGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5619,7 +5679,7 @@ impl<'a, C, A> ColumnGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5799,6 +5859,7 @@ impl<'a, C, A> TemplateUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Template)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5855,11 +5916,20 @@ impl<'a, C, A> TemplateUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5882,7 +5952,7 @@ impl<'a, C, A> TemplateUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6131,7 +6201,7 @@ impl<'a, C, A> TemplateListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6153,7 +6223,7 @@ impl<'a, C, A> TemplateListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6385,7 +6455,7 @@ impl<'a, C, A> TemplateDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6407,7 +6477,7 @@ impl<'a, C, A> TemplateDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6576,6 +6646,7 @@ impl<'a, C, A> TemplateInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Template)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6631,11 +6702,20 @@ impl<'a, C, A> TemplateInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6658,7 +6738,7 @@ impl<'a, C, A> TemplateInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6840,6 +6920,7 @@ impl<'a, C, A> TemplatePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Template)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6896,11 +6977,20 @@ impl<'a, C, A> TemplatePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6923,7 +7013,7 @@ impl<'a, C, A> TemplatePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7164,7 +7254,7 @@ impl<'a, C, A> TemplateGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7186,7 +7276,7 @@ impl<'a, C, A> TemplateGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7423,7 +7513,7 @@ impl<'a, C, A> QuerySqlGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7445,7 +7535,7 @@ impl<'a, C, A> QuerySqlGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7693,7 +7783,7 @@ impl<'a, C, A> QuerySqlCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7715,7 +7805,7 @@ impl<'a, C, A> QuerySqlCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7907,6 +7997,7 @@ impl<'a, C, A> TablePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Table)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7965,11 +8056,20 @@ impl<'a, C, A> TablePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7992,7 +8092,7 @@ impl<'a, C, A> TablePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8263,7 +8363,7 @@ impl<'a, C, A> TableReplaceRowCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8301,7 +8401,7 @@ impl<'a, C, A> TableReplaceRowCall<'a, C, A> where C: BorrowMut<hyper::Client>, response } else { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); if protocol == "simple" { @@ -8359,7 +8459,7 @@ impl<'a, C, A> TableReplaceRowCall<'a, C, A> where C: BorrowMut<hyper::Client>, let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -8387,6 +8487,7 @@ impl<'a, C, A> TableReplaceRowCall<'a, C, A> where C: BorrowMut<hyper::Client>, Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -8592,6 +8693,7 @@ impl<'a, C, A> TableUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Table)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8650,11 +8752,20 @@ impl<'a, C, A> TableUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8677,7 +8788,7 @@ impl<'a, C, A> TableUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8912,7 +9023,7 @@ impl<'a, C, A> TableDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8934,7 +9045,7 @@ impl<'a, C, A> TableDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9092,6 +9203,7 @@ impl<'a, C, A> TableInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Table)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9122,11 +9234,20 @@ impl<'a, C, A> TableInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9149,7 +9270,7 @@ impl<'a, C, A> TableInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9368,7 +9489,7 @@ impl<'a, C, A> TableGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9390,7 +9511,7 @@ impl<'a, C, A> TableGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9591,7 +9712,7 @@ impl<'a, C, A> TableListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9613,7 +9734,7 @@ impl<'a, C, A> TableListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9869,7 +9990,7 @@ impl<'a, C, A> TableImportRowCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9907,7 +10028,7 @@ impl<'a, C, A> TableImportRowCall<'a, C, A> where C: BorrowMut<hyper::Client>, A response } else { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); if protocol == "simple" { @@ -9965,7 +10086,7 @@ impl<'a, C, A> TableImportRowCall<'a, C, A> where C: BorrowMut<hyper::Client>, A let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -9993,6 +10114,7 @@ impl<'a, C, A> TableImportRowCall<'a, C, A> where C: BorrowMut<hyper::Client>, A Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -10240,7 +10362,7 @@ impl<'a, C, A> TableImportTableCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10278,7 +10400,7 @@ impl<'a, C, A> TableImportTableCall<'a, C, A> where C: BorrowMut<hyper::Client>, response } else { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); if protocol == "simple" { @@ -10336,7 +10458,7 @@ impl<'a, C, A> TableImportTableCall<'a, C, A> where C: BorrowMut<hyper::Client>, let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -10364,6 +10486,7 @@ impl<'a, C, A> TableImportTableCall<'a, C, A> where C: BorrowMut<hyper::Client>, Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -10599,7 +10722,7 @@ impl<'a, C, A> TableCopyCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10621,7 +10744,7 @@ impl<'a, C, A> TableCopyCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/games1-cli/Cargo.toml b/gen/games1-cli/Cargo.toml index 100ec148b2..225a9cd91d 100644 --- a/gen/games1-cli/Cargo.toml +++ b/gen/games1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-games1-cli" -version = "0.1.0+20150413" +version = "0.2.0+20150413" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with Games (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/games1-cli" @@ -17,15 +17,14 @@ keywords = ["games", "google", "cli"] name = "games1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-games1] path = "../games1" diff --git a/gen/games1-cli/README.md b/gen/games1-cli/README.md index f0bfc02298..16c861fb17 100644 --- a/gen/games1-cli/README.md +++ b/gen/games1-cli/README.md @@ -10,72 +10,88 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *Games* API can be found at the +[official documentation site](https://developers.google.com/games/services/). + # Usage -This documentation was generated from the *Games* API at revision *20150413*. The CLI is at version *0.1.0*. +This documentation was generated from the *Games* API at revision *20150413*. The CLI is at version *0.2.0*. ```bash - games1 [options] achievement-definitions list [-p <v>...] [-o <out>] - games1 [options] achievements increment <achievement-id> <steps-to-increment> [-p <v>...] [-o <out>] - games1 [options] achievements list <player-id> [-p <v>...] [-o <out>] - games1 [options] achievements reveal <achievement-id> [-p <v>...] [-o <out>] - games1 [options] achievements set-steps-at-least <achievement-id> <steps> [-p <v>...] [-o <out>] - games1 [options] achievements unlock <achievement-id> [-p <v>...] [-o <out>] - games1 [options] achievements update-multiple -r <kv>... [-p <v>...] [-o <out>] - games1 [options] applications get <application-id> [-p <v>...] [-o <out>] - games1 [options] applications played [-p <v>...] - games1 [options] events list-by-player [-p <v>...] [-o <out>] - games1 [options] events list-definitions [-p <v>...] [-o <out>] - games1 [options] events record -r <kv>... [-p <v>...] [-o <out>] - games1 [options] leaderboards get <leaderboard-id> [-p <v>...] [-o <out>] - games1 [options] leaderboards list [-p <v>...] [-o <out>] - games1 [options] metagame get-metagame-config [-p <v>...] [-o <out>] - games1 [options] metagame list-categories-by-player <player-id> <collection> [-p <v>...] [-o <out>] - games1 [options] players get <player-id> [-p <v>...] [-o <out>] - games1 [options] players list <collection> [-p <v>...] [-o <out>] - games1 [options] pushtokens remove -r <kv>... [-p <v>...] - games1 [options] pushtokens update -r <kv>... [-p <v>...] - games1 [options] quest-milestones claim <quest-id> <milestone-id> <request-id> [-p <v>...] - games1 [options] quests accept <quest-id> [-p <v>...] [-o <out>] - games1 [options] quests list <player-id> [-p <v>...] [-o <out>] - games1 [options] revisions check <client-revision> [-p <v>...] [-o <out>] - games1 [options] rooms create -r <kv>... [-p <v>...] [-o <out>] - games1 [options] rooms decline <room-id> [-p <v>...] [-o <out>] - games1 [options] rooms dismiss <room-id> [-p <v>...] - games1 [options] rooms get <room-id> [-p <v>...] [-o <out>] - games1 [options] rooms join <room-id> -r <kv>... [-p <v>...] [-o <out>] - games1 [options] rooms leave <room-id> -r <kv>... [-p <v>...] [-o <out>] - games1 [options] rooms list [-p <v>...] [-o <out>] - games1 [options] rooms report-status <room-id> -r <kv>... [-p <v>...] [-o <out>] - games1 [options] scores get <player-id> <leaderboard-id> <time-span> [-p <v>...] [-o <out>] - games1 [options] scores list <leaderboard-id> <collection> <time-span> [-p <v>...] [-o <out>] - games1 [options] scores list-window <leaderboard-id> <collection> <time-span> [-p <v>...] [-o <out>] - games1 [options] scores submit <leaderboard-id> <score> [-p <v>...] [-o <out>] - games1 [options] scores submit-multiple -r <kv>... [-p <v>...] [-o <out>] - games1 [options] snapshots get <snapshot-id> [-p <v>...] [-o <out>] - games1 [options] snapshots list <player-id> [-p <v>...] [-o <out>] - games1 [options] turn-based-matches cancel <match-id> [-p <v>...] - games1 [options] turn-based-matches create -r <kv>... [-p <v>...] [-o <out>] - games1 [options] turn-based-matches decline <match-id> [-p <v>...] [-o <out>] - games1 [options] turn-based-matches dismiss <match-id> [-p <v>...] - games1 [options] turn-based-matches finish <match-id> -r <kv>... [-p <v>...] [-o <out>] - games1 [options] turn-based-matches get <match-id> [-p <v>...] [-o <out>] - games1 [options] turn-based-matches join <match-id> [-p <v>...] [-o <out>] - games1 [options] turn-based-matches leave <match-id> [-p <v>...] [-o <out>] - games1 [options] turn-based-matches leave-turn <match-id> <match-version> [-p <v>...] [-o <out>] - games1 [options] turn-based-matches list [-p <v>...] [-o <out>] - games1 [options] turn-based-matches rematch <match-id> [-p <v>...] [-o <out>] - games1 [options] turn-based-matches sync [-p <v>...] [-o <out>] - games1 [options] turn-based-matches take-turn <match-id> -r <kv>... [-p <v>...] [-o <out>] +games1 [options] + achievement-definitions + list [-p <v>]... [-o <out>] + achievements + increment <achievement-id> <steps-to-increment> [-p <v>]... [-o <out>] + list <player-id> [-p <v>]... [-o <out>] + reveal <achievement-id> [-p <v>]... [-o <out>] + set-steps-at-least <achievement-id> <steps> [-p <v>]... [-o <out>] + unlock <achievement-id> [-p <v>]... [-o <out>] + update-multiple (-r <kv>)... [-p <v>]... [-o <out>] + applications + get <application-id> [-p <v>]... [-o <out>] + played [-p <v>]... + events + list-by-player [-p <v>]... [-o <out>] + list-definitions [-p <v>]... [-o <out>] + record (-r <kv>)... [-p <v>]... [-o <out>] + leaderboards + get <leaderboard-id> [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + metagame + get-metagame-config [-p <v>]... [-o <out>] + list-categories-by-player <player-id> <collection> [-p <v>]... [-o <out>] + players + get <player-id> [-p <v>]... [-o <out>] + list <collection> [-p <v>]... [-o <out>] + pushtokens + remove (-r <kv>)... [-p <v>]... + update (-r <kv>)... [-p <v>]... + quest-milestones + claim <quest-id> <milestone-id> <request-id> [-p <v>]... + quests + accept <quest-id> [-p <v>]... [-o <out>] + list <player-id> [-p <v>]... [-o <out>] + revisions + check <client-revision> [-p <v>]... [-o <out>] + rooms + create (-r <kv>)... [-p <v>]... [-o <out>] + decline <room-id> [-p <v>]... [-o <out>] + dismiss <room-id> [-p <v>]... + get <room-id> [-p <v>]... [-o <out>] + join <room-id> (-r <kv>)... [-p <v>]... [-o <out>] + leave <room-id> (-r <kv>)... [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + report-status <room-id> (-r <kv>)... [-p <v>]... [-o <out>] + scores + get <player-id> <leaderboard-id> <time-span> [-p <v>]... [-o <out>] + list <leaderboard-id> <collection> <time-span> [-p <v>]... [-o <out>] + list-window <leaderboard-id> <collection> <time-span> [-p <v>]... [-o <out>] + submit <leaderboard-id> <score> [-p <v>]... [-o <out>] + submit-multiple (-r <kv>)... [-p <v>]... [-o <out>] + snapshots + get <snapshot-id> [-p <v>]... [-o <out>] + list <player-id> [-p <v>]... [-o <out>] + turn-based-matches + cancel <match-id> [-p <v>]... + create (-r <kv>)... [-p <v>]... [-o <out>] + decline <match-id> [-p <v>]... [-o <out>] + dismiss <match-id> [-p <v>]... + finish <match-id> (-r <kv>)... [-p <v>]... [-o <out>] + get <match-id> [-p <v>]... [-o <out>] + join <match-id> [-p <v>]... [-o <out>] + leave <match-id> [-p <v>]... [-o <out>] + leave-turn <match-id> <match-version> [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + rematch <match-id> [-p <v>]... [-o <out>] + sync [-p <v>]... [-o <out>] + take-turn <match-id> (-r <kv>)... [-p <v>]... [-o <out>] games1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_games1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/games1-cli/mkdocs.yml b/gen/games1-cli/mkdocs.yml index 4892f18a93..050dad2515 100644 --- a/gen/games1-cli/mkdocs.yml +++ b/gen/games1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Games v0.1.0+20150413 +site_name: Games v0.2.0+20150413 site_url: http://byron.github.io/google-apis-rs/google-games1-cli site_description: Write integrating applications with bcore diff --git a/gen/games1-cli/src/cmn.rs b/gen/games1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/games1-cli/src/cmn.rs +++ b/gen/games1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/games1-cli/src/main.rs b/gen/games1-cli/src/main.rs index 1162501e49..92ebbe2bcb 100644 --- a/gen/games1-cli/src/main.rs +++ b/gen/games1-cli/src/main.rs @@ -2,118 +2,53 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_games1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - games1 [options] achievement-definitions list [-p <v>...] [-o <out>] - games1 [options] achievements increment <achievement-id> <steps-to-increment> [-p <v>...] [-o <out>] - games1 [options] achievements list <player-id> [-p <v>...] [-o <out>] - games1 [options] achievements reveal <achievement-id> [-p <v>...] [-o <out>] - games1 [options] achievements set-steps-at-least <achievement-id> <steps> [-p <v>...] [-o <out>] - games1 [options] achievements unlock <achievement-id> [-p <v>...] [-o <out>] - games1 [options] achievements update-multiple -r <kv>... [-p <v>...] [-o <out>] - games1 [options] applications get <application-id> [-p <v>...] [-o <out>] - games1 [options] applications played [-p <v>...] - games1 [options] events list-by-player [-p <v>...] [-o <out>] - games1 [options] events list-definitions [-p <v>...] [-o <out>] - games1 [options] events record -r <kv>... [-p <v>...] [-o <out>] - games1 [options] leaderboards get <leaderboard-id> [-p <v>...] [-o <out>] - games1 [options] leaderboards list [-p <v>...] [-o <out>] - games1 [options] metagame get-metagame-config [-p <v>...] [-o <out>] - games1 [options] metagame list-categories-by-player <player-id> <collection> [-p <v>...] [-o <out>] - games1 [options] players get <player-id> [-p <v>...] [-o <out>] - games1 [options] players list <collection> [-p <v>...] [-o <out>] - games1 [options] pushtokens remove -r <kv>... [-p <v>...] - games1 [options] pushtokens update -r <kv>... [-p <v>...] - games1 [options] quest-milestones claim <quest-id> <milestone-id> <request-id> [-p <v>...] - games1 [options] quests accept <quest-id> [-p <v>...] [-o <out>] - games1 [options] quests list <player-id> [-p <v>...] [-o <out>] - games1 [options] revisions check <client-revision> [-p <v>...] [-o <out>] - games1 [options] rooms create -r <kv>... [-p <v>...] [-o <out>] - games1 [options] rooms decline <room-id> [-p <v>...] [-o <out>] - games1 [options] rooms dismiss <room-id> [-p <v>...] - games1 [options] rooms get <room-id> [-p <v>...] [-o <out>] - games1 [options] rooms join <room-id> -r <kv>... [-p <v>...] [-o <out>] - games1 [options] rooms leave <room-id> -r <kv>... [-p <v>...] [-o <out>] - games1 [options] rooms list [-p <v>...] [-o <out>] - games1 [options] rooms report-status <room-id> -r <kv>... [-p <v>...] [-o <out>] - games1 [options] scores get <player-id> <leaderboard-id> <time-span> [-p <v>...] [-o <out>] - games1 [options] scores list <leaderboard-id> <collection> <time-span> [-p <v>...] [-o <out>] - games1 [options] scores list-window <leaderboard-id> <collection> <time-span> [-p <v>...] [-o <out>] - games1 [options] scores submit <leaderboard-id> <score> [-p <v>...] [-o <out>] - games1 [options] scores submit-multiple -r <kv>... [-p <v>...] [-o <out>] - games1 [options] snapshots get <snapshot-id> [-p <v>...] [-o <out>] - games1 [options] snapshots list <player-id> [-p <v>...] [-o <out>] - games1 [options] turn-based-matches cancel <match-id> [-p <v>...] - games1 [options] turn-based-matches create -r <kv>... [-p <v>...] [-o <out>] - games1 [options] turn-based-matches decline <match-id> [-p <v>...] [-o <out>] - games1 [options] turn-based-matches dismiss <match-id> [-p <v>...] - games1 [options] turn-based-matches finish <match-id> -r <kv>... [-p <v>...] [-o <out>] - games1 [options] turn-based-matches get <match-id> [-p <v>...] [-o <out>] - games1 [options] turn-based-matches join <match-id> [-p <v>...] [-o <out>] - games1 [options] turn-based-matches leave <match-id> [-p <v>...] [-o <out>] - games1 [options] turn-based-matches leave-turn <match-id> <match-version> [-p <v>...] [-o <out>] - games1 [options] turn-based-matches list [-p <v>...] [-o <out>] - games1 [options] turn-based-matches rematch <match-id> [-p <v>...] [-o <out>] - games1 [options] turn-based-matches sync [-p <v>...] [-o <out>] - games1 [options] turn-based-matches take-turn <match-id> -r <kv>... [-p <v>...] [-o <out>] - games1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_games1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Games<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _achievement_definitions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _achievement_definitions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.achievement_definitions().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -125,100 +60,108 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "language", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _achievements_increment(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let steps_to_increment: i32 = arg_from_str(&self.opt.arg_steps_to_increment, err, "<steps-to-increment>", "integer"); - let mut call = self.hub.achievements().increment(&self.opt.arg_achievement_id, steps_to_increment); - for parg in self.opt.arg_v.iter() { + fn _achievements_increment(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let steps_to_increment: i32 = arg_from_str(&opt.value_of("steps-to-increment").unwrap_or(""), err, "<steps-to-increment>", "integer"); + let mut call = self.hub.achievements().increment(opt.value_of("achievement-id").unwrap_or(""), steps_to_increment); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "request-id" => { call = call.request_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["request-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _achievements_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.achievements().list(&self.opt.arg_player_id); - for parg in self.opt.arg_v.iter() { + fn _achievements_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.achievements().list(opt.value_of("player-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "state" => { @@ -233,191 +176,207 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "state", "language", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _achievements_reveal(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.achievements().reveal(&self.opt.arg_achievement_id); - for parg in self.opt.arg_v.iter() { + fn _achievements_reveal(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.achievements().reveal(opt.value_of("achievement-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _achievements_set_steps_at_least(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let steps: i32 = arg_from_str(&self.opt.arg_steps, err, "<steps>", "integer"); - let mut call = self.hub.achievements().set_steps_at_least(&self.opt.arg_achievement_id, steps); - for parg in self.opt.arg_v.iter() { + fn _achievements_set_steps_at_least(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let steps: i32 = arg_from_str(&opt.value_of("steps").unwrap_or(""), err, "<steps>", "integer"); + let mut call = self.hub.achievements().set_steps_at_least(opt.value_of("achievement-id").unwrap_or(""), steps); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _achievements_unlock(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.achievements().unlock(&self.opt.arg_achievement_id); - for parg in self.opt.arg_v.iter() { + fn _achievements_unlock(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.achievements().unlock(opt.value_of("achievement-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _achievements_update_multiple(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _achievements_update_multiple(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AchievementUpdateMultipleRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -436,58 +395,63 @@ impl Engine { request.kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.achievements().update_multiple(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _applications_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.applications().get(&self.opt.arg_application_id); - for parg in self.opt.arg_v.iter() { + fn _applications_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.applications().get(opt.value_of("application-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "platform-type" => { @@ -496,94 +460,97 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["platform-type", "language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _applications_played(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _applications_played(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.applications().played(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _events_list_by_player(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _events_list_by_player(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.events().list_by_player(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -595,50 +562,54 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "language", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _events_list_definitions(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _events_list_definitions(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.events().list_definitions(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -650,52 +621,56 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "language", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _events_record(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _events_record(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::EventRecordRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -720,110 +695,119 @@ impl Engine { request.current_time_millis = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["current-time-millis", "kind", "request-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.events().record(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _leaderboards_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.leaderboards().get(&self.opt.arg_leaderboard_id); - for parg in self.opt.arg_v.iter() { + fn _leaderboards_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.leaderboards().get(opt.value_of("leaderboard-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _leaderboards_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _leaderboards_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.leaderboards().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -835,96 +819,104 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "language", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _metagame_get_metagame_config(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _metagame_get_metagame_config(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.metagame().get_metagame_config(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _metagame_list_categories_by_player(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.metagame().list_categories_by_player(&self.opt.arg_player_id, &self.opt.arg_collection); - for parg in self.opt.arg_v.iter() { + fn _metagame_list_categories_by_player(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.metagame().list_categories_by_player(opt.value_of("player-id").unwrap_or(""), opt.value_of("collection").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -936,99 +928,107 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "language", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _players_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.players().get(&self.opt.arg_player_id); - for parg in self.opt.arg_v.iter() { + fn _players_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.players().get(opt.value_of("player-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _players_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.players().list(&self.opt.arg_collection); - for parg in self.opt.arg_v.iter() { + fn _players_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.players().list(opt.value_of("collection").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1040,52 +1040,56 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "language", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _pushtokens_remove(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _pushtokens_remove(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PushTokenId::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1118,58 +1122,58 @@ impl Engine { request.ios.as_mut().unwrap().apns_environment = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["apns-device-token", "apns-environment", "ios", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.pushtokens().remove(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _pushtokens_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _pushtokens_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PushToken::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1220,149 +1224,152 @@ impl Engine { request.language = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["apns-device-token", "apns-environment", "client-revision", "id", "ios", "kind", "language"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.pushtokens().update(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _quest_milestones_claim(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.quest_milestones().claim(&self.opt.arg_quest_id, &self.opt.arg_milestone_id, &self.opt.arg_request_id); - for parg in self.opt.arg_v.iter() { + fn _quest_milestones_claim(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.quest_milestones().claim(opt.value_of("quest-id").unwrap_or(""), opt.value_of("milestone-id").unwrap_or(""), opt.value_of("request-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _quests_accept(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.quests().accept(&self.opt.arg_quest_id); - for parg in self.opt.arg_v.iter() { + fn _quests_accept(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.quests().accept(opt.value_of("quest-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _quests_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.quests().list(&self.opt.arg_player_id); - for parg in self.opt.arg_v.iter() { + fn _quests_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.quests().list(opt.value_of("player-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1374,98 +1381,106 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "language", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _revisions_check(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.revisions().check(&self.opt.arg_client_revision); - for parg in self.opt.arg_v.iter() { + fn _revisions_check(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.revisions().check(opt.value_of("client-revision").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rooms_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _rooms_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::RoomCreateRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1576,205 +1591,217 @@ impl Engine { request.request_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["android-network-subtype", "android-network-type", "auto-matching-criteria", "capabilities", "client-address", "exclusive-bitmask", "invited-player-ids", "ios-network-type", "kind", "max-auto-matching-players", "min-auto-matching-players", "network-diagnostics", "network-operator-code", "network-operator-name", "registration-latency-millis", "request-id", "variant", "xmpp-address"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.rooms().create(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rooms_decline(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rooms().decline(&self.opt.arg_room_id); - for parg in self.opt.arg_v.iter() { + fn _rooms_decline(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rooms().decline(opt.value_of("room-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rooms_dismiss(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rooms().dismiss(&self.opt.arg_room_id); - for parg in self.opt.arg_v.iter() { + fn _rooms_dismiss(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rooms().dismiss(opt.value_of("room-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _rooms_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rooms().get(&self.opt.arg_room_id); - for parg in self.opt.arg_v.iter() { + fn _rooms_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rooms().get(opt.value_of("room-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rooms_join(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _rooms_join(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::RoomJoinRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1849,63 +1876,68 @@ impl Engine { request.capabilities.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["android-network-subtype", "android-network-type", "capabilities", "client-address", "ios-network-type", "kind", "network-diagnostics", "network-operator-code", "network-operator-name", "registration-latency-millis", "xmpp-address"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.rooms().join(request, &self.opt.arg_room_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.rooms().join(request, opt.value_of("room-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rooms_leave(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _rooms_leave(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::RoomLeaveRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1961,61 +1993,66 @@ impl Engine { request.leave_diagnostics.as_mut().unwrap().android_network_type = Some(arg_from_str(value.unwrap_or("-0"), err, "leave-diagnostics.android-network-type", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["android-network-subtype", "android-network-type", "ios-network-type", "kind", "leave-diagnostics", "network-operator-code", "network-operator-name", "reason", "sockets-used"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.rooms().leave(request, &self.opt.arg_room_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.rooms().leave(request, opt.value_of("room-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rooms_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _rooms_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.rooms().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2027,52 +2064,56 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "language", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rooms_report_status(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _rooms_report_status(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::RoomP2PStatuses::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2091,61 +2132,66 @@ impl Engine { request.kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.rooms().report_status(request, &self.opt.arg_room_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.rooms().report_status(request, opt.value_of("room-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _scores_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.scores().get(&self.opt.arg_player_id, &self.opt.arg_leaderboard_id, &self.opt.arg_time_span); - for parg in self.opt.arg_v.iter() { + fn _scores_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.scores().get(opt.value_of("player-id").unwrap_or(""), opt.value_of("leaderboard-id").unwrap_or(""), opt.value_of("time-span").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2160,50 +2206,54 @@ impl Engine { "include-rank-type" => { call = call.include_rank_type(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "language", "max-results", "include-rank-type"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _scores_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.scores().list(&self.opt.arg_leaderboard_id, &self.opt.arg_collection, &self.opt.arg_time_span); - for parg in self.opt.arg_v.iter() { + fn _scores_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.scores().list(opt.value_of("leaderboard-id").unwrap_or(""), opt.value_of("collection").unwrap_or(""), opt.value_of("time-span").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2215,50 +2265,54 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "language", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _scores_list_window(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.scores().list_window(&self.opt.arg_leaderboard_id, &self.opt.arg_collection, &self.opt.arg_time_span); - for parg in self.opt.arg_v.iter() { + fn _scores_list_window(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.scores().list_window(opt.value_of("leaderboard-id").unwrap_or(""), opt.value_of("collection").unwrap_or(""), opt.value_of("time-span").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "return-top-if-absent" => { @@ -2276,50 +2330,54 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["return-top-if-absent", "results-above", "language", "max-results", "page-token"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _scores_submit(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.scores().submit(&self.opt.arg_leaderboard_id, &self.opt.arg_score); - for parg in self.opt.arg_v.iter() { + fn _scores_submit(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.scores().submit(opt.value_of("leaderboard-id").unwrap_or(""), opt.value_of("score").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "score-tag" => { @@ -2328,52 +2386,56 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language", "score-tag"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _scores_submit_multiple(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _scores_submit_multiple(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PlayerScoreSubmissionList::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2392,110 +2454,119 @@ impl Engine { request.kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.scores().submit_multiple(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _snapshots_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.snapshots().get(&self.opt.arg_snapshot_id); - for parg in self.opt.arg_v.iter() { + fn _snapshots_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.snapshots().get(opt.value_of("snapshot-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _snapshots_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.snapshots().list(&self.opt.arg_player_id); - for parg in self.opt.arg_v.iter() { + fn _snapshots_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.snapshots().list(opt.value_of("player-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2507,96 +2578,99 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "language", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _turn_based_matches_cancel(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.turn_based_matches().cancel(&self.opt.arg_match_id); - for parg in self.opt.arg_v.iter() { + fn _turn_based_matches_cancel(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.turn_based_matches().cancel(opt.value_of("match-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _turn_based_matches_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _turn_based_matches_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TurnBasedMatchCreateRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2651,156 +2725,164 @@ impl Engine { request.request_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["auto-matching-criteria", "exclusive-bitmask", "invited-player-ids", "kind", "max-auto-matching-players", "min-auto-matching-players", "request-id", "variant"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.turn_based_matches().create(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _turn_based_matches_decline(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.turn_based_matches().decline(&self.opt.arg_match_id); - for parg in self.opt.arg_v.iter() { + fn _turn_based_matches_decline(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.turn_based_matches().decline(opt.value_of("match-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _turn_based_matches_dismiss(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.turn_based_matches().dismiss(&self.opt.arg_match_id); - for parg in self.opt.arg_v.iter() { + fn _turn_based_matches_dismiss(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.turn_based_matches().dismiss(opt.value_of("match-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _turn_based_matches_finish(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _turn_based_matches_finish(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TurnBasedMatchResults::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2837,61 +2919,66 @@ impl Engine { request.match_version = Some(arg_from_str(value.unwrap_or("-0"), err, "match-version", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["data", "kind", "match-version"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.turn_based_matches().finish(request, &self.opt.arg_match_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.turn_based_matches().finish(request, opt.value_of("match-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _turn_based_matches_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.turn_based_matches().get(&self.opt.arg_match_id); - for parg in self.opt.arg_v.iter() { + fn _turn_based_matches_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.turn_based_matches().get(opt.value_of("match-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { @@ -2900,149 +2987,161 @@ impl Engine { "include-match-data" => { call = call.include_match_data(arg_from_str(value.unwrap_or("false"), err, "include-match-data", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language", "include-match-data"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _turn_based_matches_join(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.turn_based_matches().join(&self.opt.arg_match_id); - for parg in self.opt.arg_v.iter() { + fn _turn_based_matches_join(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.turn_based_matches().join(opt.value_of("match-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _turn_based_matches_leave(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.turn_based_matches().leave(&self.opt.arg_match_id); - for parg in self.opt.arg_v.iter() { + fn _turn_based_matches_leave(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.turn_based_matches().leave(opt.value_of("match-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _turn_based_matches_leave_turn(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let match_version: i32 = arg_from_str(&self.opt.arg_match_version, err, "<match-version>", "integer"); - let mut call = self.hub.turn_based_matches().leave_turn(&self.opt.arg_match_id, match_version); - for parg in self.opt.arg_v.iter() { + fn _turn_based_matches_leave_turn(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let match_version: i32 = arg_from_str(&opt.value_of("match-version").unwrap_or(""), err, "<match-version>", "integer"); + let mut call = self.hub.turn_based_matches().leave_turn(opt.value_of("match-id").unwrap_or(""), match_version); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "pending-participant-id" => { @@ -3051,50 +3150,54 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language", "pending-participant-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _turn_based_matches_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _turn_based_matches_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.turn_based_matches().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -3112,50 +3215,54 @@ impl Engine { "include-match-data" => { call = call.include_match_data(arg_from_str(value.unwrap_or("false"), err, "include-match-data", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-completed-matches", "language", "max-results", "include-match-data"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _turn_based_matches_rematch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.turn_based_matches().rematch(&self.opt.arg_match_id); - for parg in self.opt.arg_v.iter() { + fn _turn_based_matches_rematch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.turn_based_matches().rematch(opt.value_of("match-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "request-id" => { @@ -3164,50 +3271,54 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["request-id", "language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _turn_based_matches_sync(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _turn_based_matches_sync(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.turn_based_matches().sync(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -3225,52 +3336,56 @@ impl Engine { "include-match-data" => { call = call.include_match_data(arg_from_str(value.unwrap_or("false"), err, "include-match-data", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-completed-matches", "language", "max-results", "include-match-data"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _turn_based_matches_take_turn(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _turn_based_matches_take_turn(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TurnBasedMatchTurn::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3311,256 +3426,363 @@ impl Engine { request.pending_participant_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["data", "kind", "match-version", "pending-participant-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.turn_based_matches().take_turn(request, &self.opt.arg_match_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.turn_based_matches().take_turn(request, opt.value_of("match-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["language"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_achievement_definitions { - if self.opt.cmd_list { - call_result = self._achievement_definitions_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("achievement-definitions", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._achievement_definitions_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("achievement-definitions".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("achievements", Some(opt)) => { + match opt.subcommand() { + ("increment", Some(opt)) => { + call_result = self._achievements_increment(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._achievements_list(opt, dry_run, &mut err); + }, + ("reveal", Some(opt)) => { + call_result = self._achievements_reveal(opt, dry_run, &mut err); + }, + ("set-steps-at-least", Some(opt)) => { + call_result = self._achievements_set_steps_at_least(opt, dry_run, &mut err); + }, + ("unlock", Some(opt)) => { + call_result = self._achievements_unlock(opt, dry_run, &mut err); + }, + ("update-multiple", Some(opt)) => { + call_result = self._achievements_update_multiple(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("achievements".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("applications", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._applications_get(opt, dry_run, &mut err); + }, + ("played", Some(opt)) => { + call_result = self._applications_played(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("applications".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("events", Some(opt)) => { + match opt.subcommand() { + ("list-by-player", Some(opt)) => { + call_result = self._events_list_by_player(opt, dry_run, &mut err); + }, + ("list-definitions", Some(opt)) => { + call_result = self._events_list_definitions(opt, dry_run, &mut err); + }, + ("record", Some(opt)) => { + call_result = self._events_record(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("events".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("leaderboards", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._leaderboards_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._leaderboards_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("leaderboards".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("metagame", Some(opt)) => { + match opt.subcommand() { + ("get-metagame-config", Some(opt)) => { + call_result = self._metagame_get_metagame_config(opt, dry_run, &mut err); + }, + ("list-categories-by-player", Some(opt)) => { + call_result = self._metagame_list_categories_by_player(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("metagame".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("players", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._players_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._players_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("players".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("pushtokens", Some(opt)) => { + match opt.subcommand() { + ("remove", Some(opt)) => { + call_result = self._pushtokens_remove(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._pushtokens_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("pushtokens".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("quest-milestones", Some(opt)) => { + match opt.subcommand() { + ("claim", Some(opt)) => { + call_result = self._quest_milestones_claim(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("quest-milestones".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("quests", Some(opt)) => { + match opt.subcommand() { + ("accept", Some(opt)) => { + call_result = self._quests_accept(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._quests_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("quests".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("revisions", Some(opt)) => { + match opt.subcommand() { + ("check", Some(opt)) => { + call_result = self._revisions_check(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("revisions".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("rooms", Some(opt)) => { + match opt.subcommand() { + ("create", Some(opt)) => { + call_result = self._rooms_create(opt, dry_run, &mut err); + }, + ("decline", Some(opt)) => { + call_result = self._rooms_decline(opt, dry_run, &mut err); + }, + ("dismiss", Some(opt)) => { + call_result = self._rooms_dismiss(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._rooms_get(opt, dry_run, &mut err); + }, + ("join", Some(opt)) => { + call_result = self._rooms_join(opt, dry_run, &mut err); + }, + ("leave", Some(opt)) => { + call_result = self._rooms_leave(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._rooms_list(opt, dry_run, &mut err); + }, + ("report-status", Some(opt)) => { + call_result = self._rooms_report_status(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("rooms".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("scores", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._scores_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._scores_list(opt, dry_run, &mut err); + }, + ("list-window", Some(opt)) => { + call_result = self._scores_list_window(opt, dry_run, &mut err); + }, + ("submit", Some(opt)) => { + call_result = self._scores_submit(opt, dry_run, &mut err); + }, + ("submit-multiple", Some(opt)) => { + call_result = self._scores_submit_multiple(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("scores".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("snapshots", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._snapshots_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._snapshots_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("snapshots".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("turn-based-matches", Some(opt)) => { + match opt.subcommand() { + ("cancel", Some(opt)) => { + call_result = self._turn_based_matches_cancel(opt, dry_run, &mut err); + }, + ("create", Some(opt)) => { + call_result = self._turn_based_matches_create(opt, dry_run, &mut err); + }, + ("decline", Some(opt)) => { + call_result = self._turn_based_matches_decline(opt, dry_run, &mut err); + }, + ("dismiss", Some(opt)) => { + call_result = self._turn_based_matches_dismiss(opt, dry_run, &mut err); + }, + ("finish", Some(opt)) => { + call_result = self._turn_based_matches_finish(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._turn_based_matches_get(opt, dry_run, &mut err); + }, + ("join", Some(opt)) => { + call_result = self._turn_based_matches_join(opt, dry_run, &mut err); + }, + ("leave", Some(opt)) => { + call_result = self._turn_based_matches_leave(opt, dry_run, &mut err); + }, + ("leave-turn", Some(opt)) => { + call_result = self._turn_based_matches_leave_turn(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._turn_based_matches_list(opt, dry_run, &mut err); + }, + ("rematch", Some(opt)) => { + call_result = self._turn_based_matches_rematch(opt, dry_run, &mut err); + }, + ("sync", Some(opt)) => { + call_result = self._turn_based_matches_sync(opt, dry_run, &mut err); + }, + ("take-turn", Some(opt)) => { + call_result = self._turn_based_matches_take_turn(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("turn-based-matches".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_achievements { - if self.opt.cmd_increment { - call_result = self._achievements_increment(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._achievements_list(dry_run, &mut err); - } else if self.opt.cmd_reveal { - call_result = self._achievements_reveal(dry_run, &mut err); - } else if self.opt.cmd_set_steps_at_least { - call_result = self._achievements_set_steps_at_least(dry_run, &mut err); - } else if self.opt.cmd_unlock { - call_result = self._achievements_unlock(dry_run, &mut err); - } else if self.opt.cmd_update_multiple { - call_result = self._achievements_update_multiple(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_applications { - if self.opt.cmd_get { - call_result = self._applications_get(dry_run, &mut err); - } else if self.opt.cmd_played { - call_result = self._applications_played(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_events { - if self.opt.cmd_list_by_player { - call_result = self._events_list_by_player(dry_run, &mut err); - } else if self.opt.cmd_list_definitions { - call_result = self._events_list_definitions(dry_run, &mut err); - } else if self.opt.cmd_record { - call_result = self._events_record(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_leaderboards { - if self.opt.cmd_get { - call_result = self._leaderboards_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._leaderboards_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_metagame { - if self.opt.cmd_get_metagame_config { - call_result = self._metagame_get_metagame_config(dry_run, &mut err); - } else if self.opt.cmd_list_categories_by_player { - call_result = self._metagame_list_categories_by_player(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_players { - if self.opt.cmd_get { - call_result = self._players_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._players_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_pushtokens { - if self.opt.cmd_remove { - call_result = self._pushtokens_remove(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._pushtokens_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_quest_milestones { - if self.opt.cmd_claim { - call_result = self._quest_milestones_claim(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_quests { - if self.opt.cmd_accept { - call_result = self._quests_accept(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._quests_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_revisions { - if self.opt.cmd_check { - call_result = self._revisions_check(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_rooms { - if self.opt.cmd_create { - call_result = self._rooms_create(dry_run, &mut err); - } else if self.opt.cmd_decline { - call_result = self._rooms_decline(dry_run, &mut err); - } else if self.opt.cmd_dismiss { - call_result = self._rooms_dismiss(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._rooms_get(dry_run, &mut err); - } else if self.opt.cmd_join { - call_result = self._rooms_join(dry_run, &mut err); - } else if self.opt.cmd_leave { - call_result = self._rooms_leave(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._rooms_list(dry_run, &mut err); - } else if self.opt.cmd_report_status { - call_result = self._rooms_report_status(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_scores { - if self.opt.cmd_get { - call_result = self._scores_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._scores_list(dry_run, &mut err); - } else if self.opt.cmd_list_window { - call_result = self._scores_list_window(dry_run, &mut err); - } else if self.opt.cmd_submit { - call_result = self._scores_submit(dry_run, &mut err); - } else if self.opt.cmd_submit_multiple { - call_result = self._scores_submit_multiple(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_snapshots { - if self.opt.cmd_get { - call_result = self._snapshots_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._snapshots_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_turn_based_matches { - if self.opt.cmd_cancel { - call_result = self._turn_based_matches_cancel(dry_run, &mut err); - } else if self.opt.cmd_create { - call_result = self._turn_based_matches_create(dry_run, &mut err); - } else if self.opt.cmd_decline { - call_result = self._turn_based_matches_decline(dry_run, &mut err); - } else if self.opt.cmd_dismiss { - call_result = self._turn_based_matches_dismiss(dry_run, &mut err); - } else if self.opt.cmd_finish { - call_result = self._turn_based_matches_finish(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._turn_based_matches_get(dry_run, &mut err); - } else if self.opt.cmd_join { - call_result = self._turn_based_matches_join(dry_run, &mut err); - } else if self.opt.cmd_leave { - call_result = self._turn_based_matches_leave(dry_run, &mut err); - } else if self.opt.cmd_leave_turn { - call_result = self._turn_based_matches_leave_turn(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._turn_based_matches_list(dry_run, &mut err); - } else if self.opt.cmd_rematch { - call_result = self._turn_based_matches_rematch(dry_run, &mut err); - } else if self.opt.cmd_sync { - call_result = self._turn_based_matches_sync(dry_run, &mut err); - } else if self.opt.cmd_take_turn { - call_result = self._turn_based_matches_take_turn(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -3573,7 +3795,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -3586,7 +3808,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -3596,37 +3818,1330 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Games::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("achievement-definitions", "methods: 'list'", vec![ + ("list", + Some(r##"Lists all the achievement definitions for your application."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/achievement-definitions_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("achievements", "methods: 'increment', 'list', 'reveal', 'set-steps-at-least', 'unlock' and 'update-multiple'", vec![ + ("increment", + Some(r##"Increments the steps of the achievement with the given ID for the currently authenticated player."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/achievements_increment", + vec![ + (Some(r##"achievement-id"##), + None, + Some(r##"The ID of the achievement used by this method."##), + Some(true), + Some(false)), + + (Some(r##"steps-to-increment"##), + None, + Some(r##"The number of steps to increment."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists the progress for all your application's achievements for the currently authenticated player."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/achievements_list", + vec![ + (Some(r##"player-id"##), + None, + Some(r##"A player ID. A value of me may be used in place of the authenticated player's ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reveal", + Some(r##"Sets the state of the achievement with the given ID to REVEALED for the currently authenticated player."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/achievements_reveal", + vec![ + (Some(r##"achievement-id"##), + None, + Some(r##"The ID of the achievement used by this method."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-steps-at-least", + Some(r##"Sets the steps for the currently authenticated player towards unlocking an achievement. If the steps parameter is less than the current number of steps that the player already gained for the achievement, the achievement is not modified."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/achievements_set-steps-at-least", + vec![ + (Some(r##"achievement-id"##), + None, + Some(r##"The ID of the achievement used by this method."##), + Some(true), + Some(false)), + + (Some(r##"steps"##), + None, + Some(r##"The minimum value to set the steps to."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("unlock", + Some(r##"Unlocks this achievement for the currently authenticated player."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/achievements_unlock", + vec![ + (Some(r##"achievement-id"##), + None, + Some(r##"The ID of the achievement used by this method."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update-multiple", + Some(r##"Updates multiple achievements for the currently authenticated player."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/achievements_update-multiple", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("applications", "methods: 'get' and 'played'", vec![ + ("get", + Some(r##"Retrieves the metadata of the application with the given ID. If the requested application is not available for the specified platformType, the returned response will not include any instance data."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/applications_get", + vec![ + (Some(r##"application-id"##), + None, + Some(r##"The application ID from the Google Play developer console."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("played", + Some(r##"Indicate that the the currently authenticated user is playing your application."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/applications_played", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("events", "methods: 'list-by-player', 'list-definitions' and 'record'", vec![ + ("list-by-player", + Some(r##"Returns a list showing the current progress on events in this application for the currently authenticated user."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/events_list-by-player", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-definitions", + Some(r##"Returns a list of the event definitions in this application."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/events_list-definitions", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("record", + Some(r##"Records a batch of changes to the number of times events have occurred for the currently authenticated user of this application."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/events_record", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("leaderboards", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Retrieves the metadata of the leaderboard with the given ID."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/leaderboards_get", + vec![ + (Some(r##"leaderboard-id"##), + None, + Some(r##"The ID of the leaderboard."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists all the leaderboard metadata for your application."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/leaderboards_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("metagame", "methods: 'get-metagame-config' and 'list-categories-by-player'", vec![ + ("get-metagame-config", + Some(r##"Return the metagame configuration data for the calling application."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/metagame_get-metagame-config", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-categories-by-player", + Some(r##"List play data aggregated per category for the player corresponding to playerId."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/metagame_list-categories-by-player", + vec![ + (Some(r##"player-id"##), + None, + Some(r##"A player ID. A value of me may be used in place of the authenticated player's ID."##), + Some(true), + Some(false)), + + (Some(r##"collection"##), + None, + Some(r##"The collection of categories for which data will be returned."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("players", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Retrieves the Player resource with the given ID. To retrieve the player for the currently authenticated user, set playerId to me."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/players_get", + vec![ + (Some(r##"player-id"##), + None, + Some(r##"A player ID. A value of me may be used in place of the authenticated player's ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Get the collection of players for the currently authenticated user."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/players_list", + vec![ + (Some(r##"collection"##), + None, + Some(r##"Collection of players being retrieved"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("pushtokens", "methods: 'remove' and 'update'", vec![ + ("remove", + Some(r##"Removes a push token for the current user and application. Removing a non-existent push token will report success."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/pushtokens_remove", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("update", + Some(r##"Registers a push token for the current user and application."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/pushtokens_update", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("quest-milestones", "methods: 'claim'", vec![ + ("claim", + Some(r##"Report that a reward for the milestone corresponding to milestoneId for the quest corresponding to questId has been claimed by the currently authorized user."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/quest-milestones_claim", + vec![ + (Some(r##"quest-id"##), + None, + Some(r##"The ID of the quest."##), + Some(true), + Some(false)), + + (Some(r##"milestone-id"##), + None, + Some(r##"The ID of the milestone."##), + Some(true), + Some(false)), + + (Some(r##"request-id"##), + None, + Some(r##"A numeric ID to ensure that the request is handled correctly across retries. Your client application must generate this ID randomly."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("quests", "methods: 'accept' and 'list'", vec![ + ("accept", + Some(r##"Indicates that the currently authorized user will participate in the quest."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/quests_accept", + vec![ + (Some(r##"quest-id"##), + None, + Some(r##"The ID of the quest."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Get a list of quests for your application and the currently authenticated player."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/quests_list", + vec![ + (Some(r##"player-id"##), + None, + Some(r##"A player ID. A value of me may be used in place of the authenticated player's ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("revisions", "methods: 'check'", vec![ + ("check", + Some(r##"Checks whether the games client is out of date."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/revisions_check", + vec![ + (Some(r##"client-revision"##), + None, + Some(r##"The revision of the client SDK used by your application. Format: + [PLATFORM_TYPE]:[VERSION_NUMBER]. Possible values of PLATFORM_TYPE are: + + - "ANDROID" - Client is running the Android SDK. + - "IOS" - Client is running the iOS SDK. + - "WEB_APP" - Client is running as a Web App."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("rooms", "methods: 'create', 'decline', 'dismiss', 'get', 'join', 'leave', 'list' and 'report-status'", vec![ + ("create", + Some(r##"Create a room. For internal use by the Games SDK only. Calling this method directly is unsupported."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/rooms_create", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("decline", + Some(r##"Decline an invitation to join a room. For internal use by the Games SDK only. Calling this method directly is unsupported."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/rooms_decline", + vec![ + (Some(r##"room-id"##), + None, + Some(r##"The ID of the room."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("dismiss", + Some(r##"Dismiss an invitation to join a room. For internal use by the Games SDK only. Calling this method directly is unsupported."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/rooms_dismiss", + vec![ + (Some(r##"room-id"##), + None, + Some(r##"The ID of the room."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Get the data for a room."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/rooms_get", + vec![ + (Some(r##"room-id"##), + None, + Some(r##"The ID of the room."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("join", + Some(r##"Join a room. For internal use by the Games SDK only. Calling this method directly is unsupported."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/rooms_join", + vec![ + (Some(r##"room-id"##), + None, + Some(r##"The ID of the room."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("leave", + Some(r##"Leave a room. For internal use by the Games SDK only. Calling this method directly is unsupported."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/rooms_leave", + vec![ + (Some(r##"room-id"##), + None, + Some(r##"The ID of the room."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Returns invitations to join rooms."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/rooms_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("report-status", + Some(r##"Updates sent by a client reporting the status of peers in a room. For internal use by the Games SDK only. Calling this method directly is unsupported."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/rooms_report-status", + vec![ + (Some(r##"room-id"##), + None, + Some(r##"The ID of the room."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("scores", "methods: 'get', 'list', 'list-window', 'submit' and 'submit-multiple'", vec![ + ("get", + Some(r##"Get high scores, and optionally ranks, in leaderboards for the currently authenticated player. For a specific time span, leaderboardId can be set to ALL to retrieve data for all leaderboards in a given time span. + NOTE: You cannot ask for 'ALL' leaderboards and 'ALL' timeSpans in the same request; only one parameter may be set to 'ALL'."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/scores_get", + vec![ + (Some(r##"player-id"##), + None, + Some(r##"A player ID. A value of me may be used in place of the authenticated player's ID."##), + Some(true), + Some(false)), + + (Some(r##"leaderboard-id"##), + None, + Some(r##"The ID of the leaderboard. Can be set to 'ALL' to retrieve data for all leaderboards for this application."##), + Some(true), + Some(false)), + + (Some(r##"time-span"##), + None, + Some(r##"The time span for the scores and ranks you're requesting."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists the scores in a leaderboard, starting from the top."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/scores_list", + vec![ + (Some(r##"leaderboard-id"##), + None, + Some(r##"The ID of the leaderboard."##), + Some(true), + Some(false)), + + (Some(r##"collection"##), + None, + Some(r##"The collection of scores you're requesting."##), + Some(true), + Some(false)), + + (Some(r##"time-span"##), + None, + Some(r##"The time span for the scores and ranks you're requesting."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-window", + Some(r##"Lists the scores in a leaderboard around (and including) a player's score."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/scores_list-window", + vec![ + (Some(r##"leaderboard-id"##), + None, + Some(r##"The ID of the leaderboard."##), + Some(true), + Some(false)), + + (Some(r##"collection"##), + None, + Some(r##"The collection of scores you're requesting."##), + Some(true), + Some(false)), + + (Some(r##"time-span"##), + None, + Some(r##"The time span for the scores and ranks you're requesting."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("submit", + Some(r##"Submits a score to the specified leaderboard."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/scores_submit", + vec![ + (Some(r##"leaderboard-id"##), + None, + Some(r##"The ID of the leaderboard."##), + Some(true), + Some(false)), + + (Some(r##"score"##), + None, + Some(r##"The score you're submitting. The submitted score is ignored if it is worse than a previously submitted score, where worse depends on the leaderboard sort order. The meaning of the score value depends on the leaderboard format type. For fixed-point, the score represents the raw value. For time, the score represents elapsed time in milliseconds. For currency, the score represents a value in micro units."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("submit-multiple", + Some(r##"Submits multiple scores to leaderboards."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/scores_submit-multiple", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("snapshots", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Retrieves the metadata for a given snapshot ID."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/snapshots_get", + vec![ + (Some(r##"snapshot-id"##), + None, + Some(r##"The ID of the snapshot."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of snapshots created by your application for the player corresponding to the player ID."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/snapshots_list", + vec![ + (Some(r##"player-id"##), + None, + Some(r##"A player ID. A value of me may be used in place of the authenticated player's ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("turn-based-matches", "methods: 'cancel', 'create', 'decline', 'dismiss', 'finish', 'get', 'join', 'leave', 'leave-turn', 'list', 'rematch', 'sync' and 'take-turn'", vec![ + ("cancel", + Some(r##"Cancel a turn-based match."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/turn-based-matches_cancel", + vec![ + (Some(r##"match-id"##), + None, + Some(r##"The ID of the match."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("create", + Some(r##"Create a turn-based match."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/turn-based-matches_create", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("decline", + Some(r##"Decline an invitation to play a turn-based match."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/turn-based-matches_decline", + vec![ + (Some(r##"match-id"##), + None, + Some(r##"The ID of the match."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("dismiss", + Some(r##"Dismiss a turn-based match from the match list. The match will no longer show up in the list and will not generate notifications."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/turn-based-matches_dismiss", + vec![ + (Some(r##"match-id"##), + None, + Some(r##"The ID of the match."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("finish", + Some(r##"Finish a turn-based match. Each player should make this call once, after all results are in. Only the player whose turn it is may make the first call to Finish, and can pass in the final match state."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/turn-based-matches_finish", + vec![ + (Some(r##"match-id"##), + None, + Some(r##"The ID of the match."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Get the data for a turn-based match."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/turn-based-matches_get", + vec![ + (Some(r##"match-id"##), + None, + Some(r##"The ID of the match."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("join", + Some(r##"Join a turn-based match."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/turn-based-matches_join", + vec![ + (Some(r##"match-id"##), + None, + Some(r##"The ID of the match."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("leave", + Some(r##"Leave a turn-based match when it is not the current player's turn, without canceling the match."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/turn-based-matches_leave", + vec![ + (Some(r##"match-id"##), + None, + Some(r##"The ID of the match."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("leave-turn", + Some(r##"Leave a turn-based match during the current player's turn, without canceling the match."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/turn-based-matches_leave-turn", + vec![ + (Some(r##"match-id"##), + None, + Some(r##"The ID of the match."##), + Some(true), + Some(false)), + + (Some(r##"match-version"##), + None, + Some(r##"The version of the match being updated."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Returns turn-based matches the player is or was involved in."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/turn-based-matches_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("rematch", + Some(r##"Create a rematch of a match that was previously completed, with the same participants. This can be called by only one player on a match still in their list; the player must have called Finish first. Returns the newly created match; it will be the caller's turn."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/turn-based-matches_rematch", + vec![ + (Some(r##"match-id"##), + None, + Some(r##"The ID of the match."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("sync", + Some(r##"Returns turn-based matches the player is or was involved in that changed since the last sync call, with the least recent changes coming first. Matches that should be removed from the local cache will have a status of MATCH_DELETED."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/turn-based-matches_sync", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("take-turn", + Some(r##"Commit the results of a player turn."##), + "Details at http://byron.github.io/google-apis-rs/google_games1_cli/turn-based-matches_take-turn", + vec![ + (Some(r##"match-id"##), + None, + Some(r##"The ID of the match."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("games1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150413") + .about("The API for Google Play Game Services.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_games1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/games1/Cargo.toml b/gen/games1/Cargo.toml index 1aae533bbf..79d50e0a26 100644 --- a/gen/games1/Cargo.toml +++ b/gen/games1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-games1" -version = "0.1.6+20150413" +version = "0.1.7+20150413" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with Games (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/games1" @@ -15,9 +15,10 @@ keywords = ["games", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/games1/README.md b/gen/games1/README.md index 1953fd1c34..307b49e6fd 100644 --- a/gen/games1/README.md +++ b/gen/games1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-games1` library allows access to all features of the *Google Games* service. -This documentation was generated from *Games* crate version *0.1.6+20150413*, where *20150413* is the exact revision of the *games:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *Games* crate version *0.1.7+20150413*, where *20150413* is the exact revision of the *games:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *Games* *v1* API can be found at the [official documentation site](https://developers.google.com/games/services/). @@ -194,7 +194,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_games1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_games1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/games1/src/cmn.rs b/gen/games1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/games1/src/cmn.rs +++ b/gen/games1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/games1/src/lib.rs b/gen/games1/src/lib.rs index c7f320b401..d2f1920074 100644 --- a/gen/games1/src/lib.rs +++ b/gen/games1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *Games* crate version *0.1.6+20150413*, where *20150413* is the exact revision of the *games:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *Games* crate version *0.1.7+20150413*, where *20150413* is the exact revision of the *games:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *Games* *v1* API can be found at the //! [official documentation site](https://developers.google.com/games/services/). @@ -195,7 +195,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -204,7 +204,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -220,6 +219,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -346,7 +346,7 @@ impl<'a, C, A> Games<C, A> Games { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -397,7 +397,7 @@ impl<'a, C, A> Games<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -4815,7 +4815,7 @@ impl<'a, C, A> AchievementListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4837,7 +4837,7 @@ impl<'a, C, A> AchievementListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5089,7 +5089,7 @@ impl<'a, C, A> AchievementIncrementCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5111,7 +5111,7 @@ impl<'a, C, A> AchievementIncrementCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5347,7 +5347,7 @@ impl<'a, C, A> AchievementSetStepsAtLeastCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5369,7 +5369,7 @@ impl<'a, C, A> AchievementSetStepsAtLeastCall<'a, C, A> where C: BorrowMut<hyper access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5547,6 +5547,7 @@ impl<'a, C, A> AchievementUpdateMultipleCall<'a, C, A> where C: BorrowMut<hyper: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AchievementUpdateMultipleResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5577,11 +5578,20 @@ impl<'a, C, A> AchievementUpdateMultipleCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5604,7 +5614,7 @@ impl<'a, C, A> AchievementUpdateMultipleCall<'a, C, A> where C: BorrowMut<hyper: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5823,7 +5833,7 @@ impl<'a, C, A> AchievementRevealCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5845,7 +5855,7 @@ impl<'a, C, A> AchievementRevealCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6062,7 +6072,7 @@ impl<'a, C, A> AchievementUnlockCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6084,7 +6094,7 @@ impl<'a, C, A> AchievementUnlockCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6306,7 +6316,7 @@ impl<'a, C, A> LeaderboardGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6328,7 +6338,7 @@ impl<'a, C, A> LeaderboardGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6541,7 +6551,7 @@ impl<'a, C, A> LeaderboardListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6563,7 +6573,7 @@ impl<'a, C, A> LeaderboardListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6808,7 +6818,7 @@ impl<'a, C, A> MetagameListCategoriesByPlayerCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6830,7 +6840,7 @@ impl<'a, C, A> MetagameListCategoriesByPlayerCall<'a, C, A> where C: BorrowMut<h access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7052,7 +7062,7 @@ impl<'a, C, A> MetagameGetMetagameConfigCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7074,7 +7084,7 @@ impl<'a, C, A> MetagameGetMetagameConfigCall<'a, C, A> where C: BorrowMut<hyper: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7296,7 +7306,7 @@ impl<'a, C, A> PlayerListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7318,7 +7328,7 @@ impl<'a, C, A> PlayerListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7561,7 +7571,7 @@ impl<'a, C, A> PlayerGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7583,7 +7593,7 @@ impl<'a, C, A> PlayerGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7812,7 +7822,7 @@ impl<'a, C, A> QuestAcceptCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7834,7 +7844,7 @@ impl<'a, C, A> QuestAcceptCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8073,7 +8083,7 @@ impl<'a, C, A> QuestListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8095,7 +8105,7 @@ impl<'a, C, A> QuestListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8338,7 +8348,7 @@ impl<'a, C, A> SnapshotGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8360,7 +8370,7 @@ impl<'a, C, A> SnapshotGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8599,7 +8609,7 @@ impl<'a, C, A> SnapshotListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8621,7 +8631,7 @@ impl<'a, C, A> SnapshotListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8858,7 +8868,7 @@ impl<'a, C, A> TurnBasedMatcheDismisCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8880,7 +8890,7 @@ impl<'a, C, A> TurnBasedMatcheDismisCall<'a, C, A> where C: BorrowMut<hyper::Cli access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9086,7 +9096,7 @@ impl<'a, C, A> TurnBasedMatcheSyncCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9108,7 +9118,7 @@ impl<'a, C, A> TurnBasedMatcheSyncCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9355,7 +9365,7 @@ impl<'a, C, A> TurnBasedMatcheDeclineCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9377,7 +9387,7 @@ impl<'a, C, A> TurnBasedMatcheDeclineCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9611,7 +9621,7 @@ impl<'a, C, A> TurnBasedMatcheGetCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9633,7 +9643,7 @@ impl<'a, C, A> TurnBasedMatcheGetCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9817,6 +9827,7 @@ impl<'a, C, A> TurnBasedMatcheCreateCall<'a, C, A> where C: BorrowMut<hyper::Cli /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, TurnBasedMatch)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9850,11 +9861,20 @@ impl<'a, C, A> TurnBasedMatcheCreateCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9877,7 +9897,7 @@ impl<'a, C, A> TurnBasedMatcheCreateCall<'a, C, A> where C: BorrowMut<hyper::Cli request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -10108,7 +10128,7 @@ impl<'a, C, A> TurnBasedMatcheJoinCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10130,7 +10150,7 @@ impl<'a, C, A> TurnBasedMatcheJoinCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10366,7 +10386,7 @@ impl<'a, C, A> TurnBasedMatcheLeaveTurnCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10388,7 +10408,7 @@ impl<'a, C, A> TurnBasedMatcheLeaveTurnCall<'a, C, A> where C: BorrowMut<hyper:: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10628,7 +10648,7 @@ impl<'a, C, A> TurnBasedMatcheCancelCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10650,7 +10670,7 @@ impl<'a, C, A> TurnBasedMatcheCancelCall<'a, C, A> where C: BorrowMut<hyper::Cli access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10811,6 +10831,7 @@ impl<'a, C, A> TurnBasedMatcheFinishCall<'a, C, A> where C: BorrowMut<hyper::Cli /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, TurnBasedMatch)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10869,11 +10890,20 @@ impl<'a, C, A> TurnBasedMatcheFinishCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10896,7 +10926,7 @@ impl<'a, C, A> TurnBasedMatcheFinishCall<'a, C, A> where C: BorrowMut<hyper::Cli request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11137,7 +11167,7 @@ impl<'a, C, A> TurnBasedMatcheLeaveCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11159,7 +11189,7 @@ impl<'a, C, A> TurnBasedMatcheLeaveCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11382,7 +11412,7 @@ impl<'a, C, A> TurnBasedMatcheListCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11404,7 +11434,7 @@ impl<'a, C, A> TurnBasedMatcheListCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11600,6 +11630,7 @@ impl<'a, C, A> TurnBasedMatcheTakeTurnCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, TurnBasedMatch)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11658,11 +11689,20 @@ impl<'a, C, A> TurnBasedMatcheTakeTurnCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11685,7 +11725,7 @@ impl<'a, C, A> TurnBasedMatcheTakeTurnCall<'a, C, A> where C: BorrowMut<hyper::C request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11931,7 +11971,7 @@ impl<'a, C, A> TurnBasedMatcheRematchCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11953,7 +11993,7 @@ impl<'a, C, A> TurnBasedMatcheRematchCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12194,7 +12234,7 @@ impl<'a, C, A> ApplicationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12216,7 +12256,7 @@ impl<'a, C, A> ApplicationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12420,7 +12460,7 @@ impl<'a, C, A> ApplicationPlayedCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12442,7 +12482,7 @@ impl<'a, C, A> ApplicationPlayedCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12644,7 +12684,7 @@ impl<'a, C, A> RoomGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12666,7 +12706,7 @@ impl<'a, C, A> RoomGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12844,6 +12884,7 @@ impl<'a, C, A> RoomLeaveCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Room)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12902,11 +12943,20 @@ impl<'a, C, A> RoomLeaveCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12929,7 +12979,7 @@ impl<'a, C, A> RoomLeaveCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -13154,7 +13204,7 @@ impl<'a, C, A> RoomListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13176,7 +13226,7 @@ impl<'a, C, A> RoomListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -13358,6 +13408,7 @@ impl<'a, C, A> RoomReportStatuCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, RoomStatus)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13416,11 +13467,20 @@ impl<'a, C, A> RoomReportStatuCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13443,7 +13503,7 @@ impl<'a, C, A> RoomReportStatuCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -13632,6 +13692,7 @@ impl<'a, C, A> RoomCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Room)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13665,11 +13726,20 @@ impl<'a, C, A> RoomCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13692,7 +13762,7 @@ impl<'a, C, A> RoomCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -13923,7 +13993,7 @@ impl<'a, C, A> RoomDeclineCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13945,7 +14015,7 @@ impl<'a, C, A> RoomDeclineCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -14168,7 +14238,7 @@ impl<'a, C, A> RoomDismisCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14190,7 +14260,7 @@ impl<'a, C, A> RoomDismisCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -14351,6 +14421,7 @@ impl<'a, C, A> RoomJoinCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Room)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14409,11 +14480,20 @@ impl<'a, C, A> RoomJoinCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14436,7 +14516,7 @@ impl<'a, C, A> RoomJoinCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -14684,7 +14764,7 @@ impl<'a, C, A> ScoreSubmitCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14706,7 +14786,7 @@ impl<'a, C, A> ScoreSubmitCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -14966,7 +15046,7 @@ impl<'a, C, A> ScoreListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14988,7 +15068,7 @@ impl<'a, C, A> ScoreListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -15271,7 +15351,7 @@ impl<'a, C, A> ScoreGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15293,7 +15373,7 @@ impl<'a, C, A> ScoreGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -15511,6 +15591,7 @@ impl<'a, C, A> ScoreSubmitMultipleCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PlayerScoreListResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15544,11 +15625,20 @@ impl<'a, C, A> ScoreSubmitMultipleCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15571,7 +15661,7 @@ impl<'a, C, A> ScoreSubmitMultipleCall<'a, C, A> where C: BorrowMut<hyper::Clien request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -15826,7 +15916,7 @@ impl<'a, C, A> ScoreListWindowCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15848,7 +15938,7 @@ impl<'a, C, A> ScoreListWindowCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -16071,6 +16161,7 @@ impl<'a, C, A> PushtokenRemoveCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -16100,11 +16191,20 @@ impl<'a, C, A> PushtokenRemoveCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -16127,7 +16227,7 @@ impl<'a, C, A> PushtokenRemoveCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -16287,6 +16387,7 @@ impl<'a, C, A> PushtokenUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -16316,11 +16417,20 @@ impl<'a, C, A> PushtokenUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -16343,7 +16453,7 @@ impl<'a, C, A> PushtokenUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -16528,7 +16638,7 @@ impl<'a, C, A> RevisionCheckCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16550,7 +16660,7 @@ impl<'a, C, A> RevisionCheckCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -16761,7 +16871,7 @@ impl<'a, C, A> EventListDefinitionCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16783,7 +16893,7 @@ impl<'a, C, A> EventListDefinitionCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -16964,6 +17074,7 @@ impl<'a, C, A> EventRecordCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, EventUpdateResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -16997,11 +17108,20 @@ impl<'a, C, A> EventRecordCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17024,7 +17144,7 @@ impl<'a, C, A> EventRecordCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -17239,7 +17359,7 @@ impl<'a, C, A> EventListByPlayerCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17261,7 +17381,7 @@ impl<'a, C, A> EventListByPlayerCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -17492,7 +17612,7 @@ impl<'a, C, A> QuestMilestoneClaimCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17514,7 +17634,7 @@ impl<'a, C, A> QuestMilestoneClaimCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -17730,7 +17850,7 @@ impl<'a, C, A> AchievementDefinitionListCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17752,7 +17872,7 @@ impl<'a, C, A> AchievementDefinitionListCall<'a, C, A> where C: BorrowMut<hyper: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/gamesconfiguration1_configuration-cli/Cargo.toml b/gen/gamesconfiguration1_configuration-cli/Cargo.toml index 4dd1e305d7..a297d50028 100644 --- a/gen/gamesconfiguration1_configuration-cli/Cargo.toml +++ b/gen/gamesconfiguration1_configuration-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-gamesconfiguration1_configuration-cli" -version = "0.1.0+20150413" +version = "0.2.0+20150413" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with Games Configuration (protocol v1configuration)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/gamesconfiguration1_configuration-cli" @@ -17,15 +17,14 @@ keywords = ["gamesConfiguration", "google", "cli"] name = "gamesconfiguration1-configuration" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-gamesconfiguration1_configuration] path = "../gamesconfiguration1_configuration" diff --git a/gen/gamesconfiguration1_configuration-cli/README.md b/gen/gamesconfiguration1_configuration-cli/README.md index 2b61bdba9e..3c7c46b1a9 100644 --- a/gen/gamesconfiguration1_configuration-cli/README.md +++ b/gen/gamesconfiguration1_configuration-cli/README.md @@ -10,33 +10,37 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *Games Configuration* API can be found at the +[official documentation site](https://developers.google.com/games/services). + # Usage -This documentation was generated from the *Games Configuration* API at revision *20150413*. The CLI is at version *0.1.0*. +This documentation was generated from the *Games Configuration* API at revision *20150413*. The CLI is at version *0.2.0*. ```bash - gamesconfiguration1-configuration [options] achievement-configurations delete <achievement-id> [-p <v>...] - gamesconfiguration1-configuration [options] achievement-configurations get <achievement-id> [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] achievement-configurations insert <application-id> -r <kv>... [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] achievement-configurations list <application-id> [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] achievement-configurations patch <achievement-id> -r <kv>... [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] achievement-configurations update <achievement-id> -r <kv>... [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] image-configurations upload <resource-id> <image-type> -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] leaderboard-configurations delete <leaderboard-id> [-p <v>...] - gamesconfiguration1-configuration [options] leaderboard-configurations get <leaderboard-id> [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] leaderboard-configurations insert <application-id> -r <kv>... [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] leaderboard-configurations list <application-id> [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] leaderboard-configurations patch <leaderboard-id> -r <kv>... [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] leaderboard-configurations update <leaderboard-id> -r <kv>... [-p <v>...] [-o <out>] +gamesconfiguration1-configuration [options] + achievement-configurations + delete <achievement-id> [-p <v>]... + get <achievement-id> [-p <v>]... [-o <out>] + insert <application-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <application-id> [-p <v>]... [-o <out>] + patch <achievement-id> (-r <kv>)... [-p <v>]... [-o <out>] + update <achievement-id> (-r <kv>)... [-p <v>]... [-o <out>] + image-configurations + upload <resource-id> <image-type> (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + leaderboard-configurations + delete <leaderboard-id> [-p <v>]... + get <leaderboard-id> [-p <v>]... [-o <out>] + insert <application-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <application-id> [-p <v>]... [-o <out>] + patch <leaderboard-id> (-r <kv>)... [-p <v>]... [-o <out>] + update <leaderboard-id> (-r <kv>)... [-p <v>]... [-o <out>] gamesconfiguration1-configuration --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/gamesconfiguration1_configuration-cli/mkdocs.yml b/gen/gamesconfiguration1_configuration-cli/mkdocs.yml index 377eefdc1b..f35f7c1ce9 100644 --- a/gen/gamesconfiguration1_configuration-cli/mkdocs.yml +++ b/gen/gamesconfiguration1_configuration-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Games Configuration v0.1.0+20150413 +site_name: Games Configuration v0.2.0+20150413 site_url: http://byron.github.io/google-apis-rs/google-gamesconfiguration1_configuration-cli site_description: Write integrating applications with bcore diff --git a/gen/gamesconfiguration1_configuration-cli/src/cmn.rs b/gen/gamesconfiguration1_configuration-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/gamesconfiguration1_configuration-cli/src/cmn.rs +++ b/gen/gamesconfiguration1_configuration-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/gamesconfiguration1_configuration-cli/src/main.rs b/gen/gamesconfiguration1_configuration-cli/src/main.rs index 346ecdf6d3..3974daf63e 100644 --- a/gen/gamesconfiguration1_configuration-cli/src/main.rs +++ b/gen/gamesconfiguration1_configuration-cli/src/main.rs @@ -2,897 +2,148 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_gamesconfiguration1_configuration as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - gamesconfiguration1-configuration [options] achievement-configurations delete <achievement-id> [-p <v>...] - gamesconfiguration1-configuration [options] achievement-configurations get <achievement-id> [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] achievement-configurations insert <application-id> -r <kv>... [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] achievement-configurations list <application-id> [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] achievement-configurations patch <achievement-id> -r <kv>... [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] achievement-configurations update <achievement-id> -r <kv>... [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] image-configurations upload <resource-id> <image-type> -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] leaderboard-configurations delete <leaderboard-id> [-p <v>...] - gamesconfiguration1-configuration [options] leaderboard-configurations get <leaderboard-id> [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] leaderboard-configurations insert <application-id> -r <kv>... [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] leaderboard-configurations list <application-id> [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] leaderboard-configurations patch <leaderboard-id> -r <kv>... [-p <v>...] [-o <out>] - gamesconfiguration1-configuration [options] leaderboard-configurations update <leaderboard-id> -r <kv>... [-p <v>...] [-o <out>] - gamesconfiguration1-configuration --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::GamesConfiguration<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _achievement_configurations_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.achievement_configurations().delete(&self.opt.arg_achievement_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _achievement_configurations_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.achievement_configurations().delete(opt.value_of("achievement-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _achievement_configurations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.achievement_configurations().get(&self.opt.arg_achievement_id); - for parg in self.opt.arg_v.iter() { + fn _achievement_configurations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.achievement_configurations().get(opt.value_of("achievement-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _achievement_configurations_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - - let mut request = api::AchievementConfiguration::default(); - let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { - let last_errc = err.issues.len(); - let (key, value) = parse_kv_arg(&*kvarg, err, false); - let mut temp_cursor = field_cursor.clone(); - if let Err(field_err) = temp_cursor.set(&*key) { - err.issues.push(field_err); - } - if value.is_none() { - field_cursor = temp_cursor.clone(); - if err.issues.len() > last_errc { - err.issues.remove(last_errc); - } - continue; - } - fn request_draft_description_init(request: &mut api::AchievementConfiguration) { - request_draft_init(request); - if request.draft.as_mut().unwrap().description.is_none() { - request.draft.as_mut().unwrap().description = Some(Default::default()); - } - } - - fn request_draft_init(request: &mut api::AchievementConfiguration) { - if request.draft.is_none() { - request.draft = Some(Default::default()); - } - } - - fn request_draft_name_init(request: &mut api::AchievementConfiguration) { - request_draft_init(request); - if request.draft.as_mut().unwrap().name.is_none() { - request.draft.as_mut().unwrap().name = Some(Default::default()); - } - } - - fn request_published_description_init(request: &mut api::AchievementConfiguration) { - request_published_init(request); - if request.published.as_mut().unwrap().description.is_none() { - request.published.as_mut().unwrap().description = Some(Default::default()); - } - } - - fn request_published_init(request: &mut api::AchievementConfiguration) { - if request.published.is_none() { - request.published = Some(Default::default()); - } - } - - fn request_published_name_init(request: &mut api::AchievementConfiguration) { - request_published_init(request); - if request.published.as_mut().unwrap().name.is_none() { - request.published.as_mut().unwrap().name = Some(Default::default()); - } - } - - match &temp_cursor.to_string()[..] { - "achievement-type" => { - request.achievement_type = Some(value.unwrap_or("").to_string()); - }, - "steps-to-unlock" => { - request.steps_to_unlock = Some(arg_from_str(value.unwrap_or("-0"), err, "steps-to-unlock", "integer")); - }, - "kind" => { - request.kind = Some(value.unwrap_or("").to_string()); - }, - "initial-state" => { - request.initial_state = Some(value.unwrap_or("").to_string()); - }, - "token" => { - request.token = Some(value.unwrap_or("").to_string()); - }, - "draft.kind" => { - request_draft_init(&mut request); - request.draft.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "draft.description.kind" => { - request_draft_description_init(&mut request); - request.draft.as_mut().unwrap().description.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "draft.icon-url" => { - request_draft_description_init(&mut request); - request.draft.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); - }, - "draft.point-value" => { - request_draft_description_init(&mut request); - request.draft.as_mut().unwrap().point_value = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.point-value", "integer")); - }, - "draft.sort-rank" => { - request_draft_description_init(&mut request); - request.draft.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.sort-rank", "integer")); - }, - "draft.name.kind" => { - request_draft_name_init(&mut request); - request.draft.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.kind" => { - request_published_init(&mut request); - request.published.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.description.kind" => { - request_published_description_init(&mut request); - request.published.as_mut().unwrap().description.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.icon-url" => { - request_published_description_init(&mut request); - request.published.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); - }, - "published.point-value" => { - request_published_description_init(&mut request); - request.published.as_mut().unwrap().point_value = Some(arg_from_str(value.unwrap_or("-0"), err, "published.point-value", "integer")); - }, - "published.sort-rank" => { - request_published_description_init(&mut request); - request.published.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "published.sort-rank", "integer")); - }, - "published.name.kind" => { - request_published_name_init(&mut request); - request.published.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "id" => { - request_published_init(&mut request); - request.id = Some(value.unwrap_or("").to_string()); - }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } } } } - let mut call = self.hub.achievement_configurations().insert(request, &self.opt.arg_application_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _achievement_configurations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.achievement_configurations().list(&self.opt.arg_application_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "page-token" => { - call = call.page_token(value.unwrap_or("")); - }, - "max-results" => { - call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); - }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _achievement_configurations_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - - let mut request = api::AchievementConfiguration::default(); - let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { - let last_errc = err.issues.len(); - let (key, value) = parse_kv_arg(&*kvarg, err, false); - let mut temp_cursor = field_cursor.clone(); - if let Err(field_err) = temp_cursor.set(&*key) { - err.issues.push(field_err); - } - if value.is_none() { - field_cursor = temp_cursor.clone(); - if err.issues.len() > last_errc { - err.issues.remove(last_errc); - } - continue; - } - fn request_draft_description_init(request: &mut api::AchievementConfiguration) { - request_draft_init(request); - if request.draft.as_mut().unwrap().description.is_none() { - request.draft.as_mut().unwrap().description = Some(Default::default()); - } - } - - fn request_draft_init(request: &mut api::AchievementConfiguration) { - if request.draft.is_none() { - request.draft = Some(Default::default()); - } - } - - fn request_draft_name_init(request: &mut api::AchievementConfiguration) { - request_draft_init(request); - if request.draft.as_mut().unwrap().name.is_none() { - request.draft.as_mut().unwrap().name = Some(Default::default()); - } - } - - fn request_published_description_init(request: &mut api::AchievementConfiguration) { - request_published_init(request); - if request.published.as_mut().unwrap().description.is_none() { - request.published.as_mut().unwrap().description = Some(Default::default()); - } - } - - fn request_published_init(request: &mut api::AchievementConfiguration) { - if request.published.is_none() { - request.published = Some(Default::default()); - } - } - - fn request_published_name_init(request: &mut api::AchievementConfiguration) { - request_published_init(request); - if request.published.as_mut().unwrap().name.is_none() { - request.published.as_mut().unwrap().name = Some(Default::default()); - } - } - - match &temp_cursor.to_string()[..] { - "achievement-type" => { - request.achievement_type = Some(value.unwrap_or("").to_string()); - }, - "steps-to-unlock" => { - request.steps_to_unlock = Some(arg_from_str(value.unwrap_or("-0"), err, "steps-to-unlock", "integer")); - }, - "kind" => { - request.kind = Some(value.unwrap_or("").to_string()); - }, - "initial-state" => { - request.initial_state = Some(value.unwrap_or("").to_string()); - }, - "token" => { - request.token = Some(value.unwrap_or("").to_string()); - }, - "draft.kind" => { - request_draft_init(&mut request); - request.draft.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "draft.description.kind" => { - request_draft_description_init(&mut request); - request.draft.as_mut().unwrap().description.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "draft.icon-url" => { - request_draft_description_init(&mut request); - request.draft.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); - }, - "draft.point-value" => { - request_draft_description_init(&mut request); - request.draft.as_mut().unwrap().point_value = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.point-value", "integer")); - }, - "draft.sort-rank" => { - request_draft_description_init(&mut request); - request.draft.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.sort-rank", "integer")); - }, - "draft.name.kind" => { - request_draft_name_init(&mut request); - request.draft.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.kind" => { - request_published_init(&mut request); - request.published.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.description.kind" => { - request_published_description_init(&mut request); - request.published.as_mut().unwrap().description.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.icon-url" => { - request_published_description_init(&mut request); - request.published.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); - }, - "published.point-value" => { - request_published_description_init(&mut request); - request.published.as_mut().unwrap().point_value = Some(arg_from_str(value.unwrap_or("-0"), err, "published.point-value", "integer")); - }, - "published.sort-rank" => { - request_published_description_init(&mut request); - request.published.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "published.sort-rank", "integer")); - }, - "published.name.kind" => { - request_published_name_init(&mut request); - request.published.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "id" => { - request_published_init(&mut request); - request.id = Some(value.unwrap_or("").to_string()); - }, - _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); - } - } - } - let mut call = self.hub.achievement_configurations().patch(request, &self.opt.arg_achievement_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _achievement_configurations_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - - let mut request = api::AchievementConfiguration::default(); - let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { - let last_errc = err.issues.len(); - let (key, value) = parse_kv_arg(&*kvarg, err, false); - let mut temp_cursor = field_cursor.clone(); - if let Err(field_err) = temp_cursor.set(&*key) { - err.issues.push(field_err); - } - if value.is_none() { - field_cursor = temp_cursor.clone(); - if err.issues.len() > last_errc { - err.issues.remove(last_errc); - } - continue; - } - fn request_draft_description_init(request: &mut api::AchievementConfiguration) { - request_draft_init(request); - if request.draft.as_mut().unwrap().description.is_none() { - request.draft.as_mut().unwrap().description = Some(Default::default()); - } - } - - fn request_draft_init(request: &mut api::AchievementConfiguration) { - if request.draft.is_none() { - request.draft = Some(Default::default()); - } - } - - fn request_draft_name_init(request: &mut api::AchievementConfiguration) { - request_draft_init(request); - if request.draft.as_mut().unwrap().name.is_none() { - request.draft.as_mut().unwrap().name = Some(Default::default()); - } - } - - fn request_published_description_init(request: &mut api::AchievementConfiguration) { - request_published_init(request); - if request.published.as_mut().unwrap().description.is_none() { - request.published.as_mut().unwrap().description = Some(Default::default()); - } - } - - fn request_published_init(request: &mut api::AchievementConfiguration) { - if request.published.is_none() { - request.published = Some(Default::default()); - } - } - - fn request_published_name_init(request: &mut api::AchievementConfiguration) { - request_published_init(request); - if request.published.as_mut().unwrap().name.is_none() { - request.published.as_mut().unwrap().name = Some(Default::default()); - } - } - - match &temp_cursor.to_string()[..] { - "achievement-type" => { - request.achievement_type = Some(value.unwrap_or("").to_string()); - }, - "steps-to-unlock" => { - request.steps_to_unlock = Some(arg_from_str(value.unwrap_or("-0"), err, "steps-to-unlock", "integer")); - }, - "kind" => { - request.kind = Some(value.unwrap_or("").to_string()); - }, - "initial-state" => { - request.initial_state = Some(value.unwrap_or("").to_string()); - }, - "token" => { - request.token = Some(value.unwrap_or("").to_string()); - }, - "draft.kind" => { - request_draft_init(&mut request); - request.draft.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "draft.description.kind" => { - request_draft_description_init(&mut request); - request.draft.as_mut().unwrap().description.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "draft.icon-url" => { - request_draft_description_init(&mut request); - request.draft.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); - }, - "draft.point-value" => { - request_draft_description_init(&mut request); - request.draft.as_mut().unwrap().point_value = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.point-value", "integer")); - }, - "draft.sort-rank" => { - request_draft_description_init(&mut request); - request.draft.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.sort-rank", "integer")); - }, - "draft.name.kind" => { - request_draft_name_init(&mut request); - request.draft.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.kind" => { - request_published_init(&mut request); - request.published.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.description.kind" => { - request_published_description_init(&mut request); - request.published.as_mut().unwrap().description.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.icon-url" => { - request_published_description_init(&mut request); - request.published.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); - }, - "published.point-value" => { - request_published_description_init(&mut request); - request.published.as_mut().unwrap().point_value = Some(arg_from_str(value.unwrap_or("-0"), err, "published.point-value", "integer")); - }, - "published.sort-rank" => { - request_published_description_init(&mut request); - request.published.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "published.sort-rank", "integer")); - }, - "published.name.kind" => { - request_published_name_init(&mut request); - request.published.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "id" => { - request_published_init(&mut request); - request.id = Some(value.unwrap_or("").to_string()); - }, - _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); - } - } - } - let mut call = self.hub.achievement_configurations().update(request, &self.opt.arg_achievement_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _image_configurations_upload(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.image_configurations().upload(&self.opt.arg_resource_id, &self.opt.arg_image_type); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _leaderboard_configurations_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.leaderboard_configurations().delete(&self.opt.arg_leaderboard_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok(mut response) => { - None - } - } - } - } - - fn _leaderboard_configurations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.leaderboard_configurations().get(&self.opt.arg_leaderboard_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _leaderboard_configurations_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _achievement_configurations_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { - let mut request = api::LeaderboardConfiguration::default(); + let mut request = api::AchievementConfiguration::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -906,321 +157,172 @@ impl Engine { } continue; } - fn request_draft_init(request: &mut api::LeaderboardConfiguration) { + fn request_draft_description_init(request: &mut api::AchievementConfiguration) { + request_draft_init(request); + if request.draft.as_mut().unwrap().description.is_none() { + request.draft.as_mut().unwrap().description = Some(Default::default()); + } + } + + fn request_draft_init(request: &mut api::AchievementConfiguration) { if request.draft.is_none() { request.draft = Some(Default::default()); } } - fn request_draft_name_init(request: &mut api::LeaderboardConfiguration) { + fn request_draft_name_init(request: &mut api::AchievementConfiguration) { request_draft_init(request); if request.draft.as_mut().unwrap().name.is_none() { request.draft.as_mut().unwrap().name = Some(Default::default()); } } - fn request_draft_score_format_init(request: &mut api::LeaderboardConfiguration) { - request_draft_init(request); - if request.draft.as_mut().unwrap().score_format.is_none() { - request.draft.as_mut().unwrap().score_format = Some(Default::default()); + fn request_published_description_init(request: &mut api::AchievementConfiguration) { + request_published_init(request); + if request.published.as_mut().unwrap().description.is_none() { + request.published.as_mut().unwrap().description = Some(Default::default()); } } - fn request_draft_score_format_suffix_few_init(request: &mut api::LeaderboardConfiguration) { - request_draft_score_format_suffix_init(request); - if request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().few.is_none() { - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().few = Some(Default::default()); - } - } - - fn request_draft_score_format_suffix_init(request: &mut api::LeaderboardConfiguration) { - request_draft_score_format_init(request); - if request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.is_none() { - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix = Some(Default::default()); - } - } - - fn request_draft_score_format_suffix_many_init(request: &mut api::LeaderboardConfiguration) { - request_draft_score_format_suffix_init(request); - if request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().many.is_none() { - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().many = Some(Default::default()); - } - } - - fn request_draft_score_format_suffix_one_init(request: &mut api::LeaderboardConfiguration) { - request_draft_score_format_suffix_init(request); - if request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().one.is_none() { - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().one = Some(Default::default()); - } - } - - fn request_draft_score_format_suffix_other_init(request: &mut api::LeaderboardConfiguration) { - request_draft_score_format_suffix_init(request); - if request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().other.is_none() { - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().other = Some(Default::default()); - } - } - - fn request_draft_score_format_suffix_two_init(request: &mut api::LeaderboardConfiguration) { - request_draft_score_format_suffix_init(request); - if request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().two.is_none() { - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().two = Some(Default::default()); - } - } - - fn request_draft_score_format_suffix_zero_init(request: &mut api::LeaderboardConfiguration) { - request_draft_score_format_suffix_init(request); - if request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().zero.is_none() { - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().zero = Some(Default::default()); - } - } - - fn request_published_init(request: &mut api::LeaderboardConfiguration) { + fn request_published_init(request: &mut api::AchievementConfiguration) { if request.published.is_none() { request.published = Some(Default::default()); } } - fn request_published_name_init(request: &mut api::LeaderboardConfiguration) { + fn request_published_name_init(request: &mut api::AchievementConfiguration) { request_published_init(request); if request.published.as_mut().unwrap().name.is_none() { request.published.as_mut().unwrap().name = Some(Default::default()); } } - fn request_published_score_format_init(request: &mut api::LeaderboardConfiguration) { - request_published_init(request); - if request.published.as_mut().unwrap().score_format.is_none() { - request.published.as_mut().unwrap().score_format = Some(Default::default()); - } - } - - fn request_published_score_format_suffix_few_init(request: &mut api::LeaderboardConfiguration) { - request_published_score_format_suffix_init(request); - if request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().few.is_none() { - request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().few = Some(Default::default()); - } - } - - fn request_published_score_format_suffix_init(request: &mut api::LeaderboardConfiguration) { - request_published_score_format_init(request); - if request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.is_none() { - request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix = Some(Default::default()); - } - } - - fn request_published_score_format_suffix_many_init(request: &mut api::LeaderboardConfiguration) { - request_published_score_format_suffix_init(request); - if request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().many.is_none() { - request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().many = Some(Default::default()); - } - } - - fn request_published_score_format_suffix_one_init(request: &mut api::LeaderboardConfiguration) { - request_published_score_format_suffix_init(request); - if request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().one.is_none() { - request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().one = Some(Default::default()); - } - } - - fn request_published_score_format_suffix_other_init(request: &mut api::LeaderboardConfiguration) { - request_published_score_format_suffix_init(request); - if request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().other.is_none() { - request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().other = Some(Default::default()); - } - } - - fn request_published_score_format_suffix_two_init(request: &mut api::LeaderboardConfiguration) { - request_published_score_format_suffix_init(request); - if request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().two.is_none() { - request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().two = Some(Default::default()); - } - } - - fn request_published_score_format_suffix_zero_init(request: &mut api::LeaderboardConfiguration) { - request_published_score_format_suffix_init(request); - if request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().zero.is_none() { - request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().zero = Some(Default::default()); - } - } - match &temp_cursor.to_string()[..] { + "achievement-type" => { + request.achievement_type = Some(value.unwrap_or("").to_string()); + }, + "steps-to-unlock" => { + request.steps_to_unlock = Some(arg_from_str(value.unwrap_or("-0"), err, "steps-to-unlock", "integer")); + }, "kind" => { request.kind = Some(value.unwrap_or("").to_string()); }, - "score-order" => { - request.score_order = Some(value.unwrap_or("").to_string()); - }, - "score-min" => { - request.score_min = Some(value.unwrap_or("").to_string()); + "initial-state" => { + request.initial_state = Some(value.unwrap_or("").to_string()); }, "token" => { request.token = Some(value.unwrap_or("").to_string()); }, - "score-max" => { - request.score_max = Some(value.unwrap_or("").to_string()); + "draft.kind" => { + request_draft_init(&mut request); + request.draft.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); }, - "published.score-format.currency-code" => { - request_published_score_format_init(&mut request); - request.published.as_mut().unwrap().score_format.as_mut().unwrap().currency_code = Some(value.unwrap_or("").to_string()); - }, - "published.score-format.suffix.many.kind" => { - request_published_score_format_suffix_many_init(&mut request); - request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().many.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.score-format.suffix.two.kind" => { - request_published_score_format_suffix_two_init(&mut request); - request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().two.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.score-format.suffix.one.kind" => { - request_published_score_format_suffix_one_init(&mut request); - request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().one.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.score-format.suffix.few.kind" => { - request_published_score_format_suffix_few_init(&mut request); - request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().few.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.score-format.suffix.zero.kind" => { - request_published_score_format_suffix_zero_init(&mut request); - request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().zero.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.score-format.suffix.other.kind" => { - request_published_score_format_suffix_other_init(&mut request); - request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().other.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.score-format.number-format-type" => { - request_published_score_format_suffix_init(&mut request); - request.published.as_mut().unwrap().score_format.as_mut().unwrap().number_format_type = Some(value.unwrap_or("").to_string()); - }, - "published.score-format.num-decimal-places" => { - request_published_score_format_suffix_init(&mut request); - request.published.as_mut().unwrap().score_format.as_mut().unwrap().num_decimal_places = Some(arg_from_str(value.unwrap_or("-0"), err, "published.score-format.num-decimal-places", "integer")); - }, - "published.icon-url" => { - request_published_score_format_init(&mut request); - request.published.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); - }, - "published.kind" => { - request_published_score_format_init(&mut request); - request.published.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.name.kind" => { - request_published_name_init(&mut request); - request.published.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "published.sort-rank" => { - request_published_name_init(&mut request); - request.published.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "published.sort-rank", "integer")); - }, - "draft.score-format.currency-code" => { - request_draft_score_format_init(&mut request); - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().currency_code = Some(value.unwrap_or("").to_string()); - }, - "draft.score-format.suffix.many.kind" => { - request_draft_score_format_suffix_many_init(&mut request); - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().many.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "draft.score-format.suffix.two.kind" => { - request_draft_score_format_suffix_two_init(&mut request); - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().two.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "draft.score-format.suffix.one.kind" => { - request_draft_score_format_suffix_one_init(&mut request); - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().one.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "draft.score-format.suffix.few.kind" => { - request_draft_score_format_suffix_few_init(&mut request); - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().few.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "draft.score-format.suffix.zero.kind" => { - request_draft_score_format_suffix_zero_init(&mut request); - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().zero.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "draft.score-format.suffix.other.kind" => { - request_draft_score_format_suffix_other_init(&mut request); - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().other.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "draft.score-format.number-format-type" => { - request_draft_score_format_suffix_init(&mut request); - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().number_format_type = Some(value.unwrap_or("").to_string()); - }, - "draft.score-format.num-decimal-places" => { - request_draft_score_format_suffix_init(&mut request); - request.draft.as_mut().unwrap().score_format.as_mut().unwrap().num_decimal_places = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.score-format.num-decimal-places", "integer")); + "draft.description.kind" => { + request_draft_description_init(&mut request); + request.draft.as_mut().unwrap().description.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); }, "draft.icon-url" => { - request_draft_score_format_init(&mut request); + request_draft_description_init(&mut request); request.draft.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); }, - "draft.kind" => { - request_draft_score_format_init(&mut request); - request.draft.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + "draft.point-value" => { + request_draft_description_init(&mut request); + request.draft.as_mut().unwrap().point_value = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.point-value", "integer")); + }, + "draft.sort-rank" => { + request_draft_description_init(&mut request); + request.draft.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.sort-rank", "integer")); }, "draft.name.kind" => { request_draft_name_init(&mut request); request.draft.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); }, - "draft.sort-rank" => { - request_draft_name_init(&mut request); - request.draft.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.sort-rank", "integer")); + "published.kind" => { + request_published_init(&mut request); + request.published.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.description.kind" => { + request_published_description_init(&mut request); + request.published.as_mut().unwrap().description.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.icon-url" => { + request_published_description_init(&mut request); + request.published.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); + }, + "published.point-value" => { + request_published_description_init(&mut request); + request.published.as_mut().unwrap().point_value = Some(arg_from_str(value.unwrap_or("-0"), err, "published.point-value", "integer")); + }, + "published.sort-rank" => { + request_published_description_init(&mut request); + request.published.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "published.sort-rank", "integer")); + }, + "published.name.kind" => { + request_published_name_init(&mut request); + request.published.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); }, "id" => { - request_draft_init(&mut request); + request_published_init(&mut request); request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["achievement-type", "description", "draft", "icon-url", "id", "initial-state", "kind", "name", "point-value", "published", "sort-rank", "steps-to-unlock", "token"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.leaderboard_configurations().insert(request, &self.opt.arg_application_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.achievement_configurations().insert(request, opt.value_of("application-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _leaderboard_configurations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.leaderboard_configurations().list(&self.opt.arg_application_id); - for parg in self.opt.arg_v.iter() { + fn _achievement_configurations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.achievement_configurations().list(opt.value_of("application-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1229,52 +331,565 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _leaderboard_configurations_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _achievement_configurations_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::AchievementConfiguration::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_draft_description_init(request: &mut api::AchievementConfiguration) { + request_draft_init(request); + if request.draft.as_mut().unwrap().description.is_none() { + request.draft.as_mut().unwrap().description = Some(Default::default()); + } + } + + fn request_draft_init(request: &mut api::AchievementConfiguration) { + if request.draft.is_none() { + request.draft = Some(Default::default()); + } + } + + fn request_draft_name_init(request: &mut api::AchievementConfiguration) { + request_draft_init(request); + if request.draft.as_mut().unwrap().name.is_none() { + request.draft.as_mut().unwrap().name = Some(Default::default()); + } + } + + fn request_published_description_init(request: &mut api::AchievementConfiguration) { + request_published_init(request); + if request.published.as_mut().unwrap().description.is_none() { + request.published.as_mut().unwrap().description = Some(Default::default()); + } + } + + fn request_published_init(request: &mut api::AchievementConfiguration) { + if request.published.is_none() { + request.published = Some(Default::default()); + } + } + + fn request_published_name_init(request: &mut api::AchievementConfiguration) { + request_published_init(request); + if request.published.as_mut().unwrap().name.is_none() { + request.published.as_mut().unwrap().name = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "achievement-type" => { + request.achievement_type = Some(value.unwrap_or("").to_string()); + }, + "steps-to-unlock" => { + request.steps_to_unlock = Some(arg_from_str(value.unwrap_or("-0"), err, "steps-to-unlock", "integer")); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "initial-state" => { + request.initial_state = Some(value.unwrap_or("").to_string()); + }, + "token" => { + request.token = Some(value.unwrap_or("").to_string()); + }, + "draft.kind" => { + request_draft_init(&mut request); + request.draft.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "draft.description.kind" => { + request_draft_description_init(&mut request); + request.draft.as_mut().unwrap().description.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "draft.icon-url" => { + request_draft_description_init(&mut request); + request.draft.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); + }, + "draft.point-value" => { + request_draft_description_init(&mut request); + request.draft.as_mut().unwrap().point_value = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.point-value", "integer")); + }, + "draft.sort-rank" => { + request_draft_description_init(&mut request); + request.draft.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.sort-rank", "integer")); + }, + "draft.name.kind" => { + request_draft_name_init(&mut request); + request.draft.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.kind" => { + request_published_init(&mut request); + request.published.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.description.kind" => { + request_published_description_init(&mut request); + request.published.as_mut().unwrap().description.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.icon-url" => { + request_published_description_init(&mut request); + request.published.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); + }, + "published.point-value" => { + request_published_description_init(&mut request); + request.published.as_mut().unwrap().point_value = Some(arg_from_str(value.unwrap_or("-0"), err, "published.point-value", "integer")); + }, + "published.sort-rank" => { + request_published_description_init(&mut request); + request.published.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "published.sort-rank", "integer")); + }, + "published.name.kind" => { + request_published_name_init(&mut request); + request.published.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_published_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["achievement-type", "description", "draft", "icon-url", "id", "initial-state", "kind", "name", "point-value", "published", "sort-rank", "steps-to-unlock", "token"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.achievement_configurations().patch(request, opt.value_of("achievement-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _achievement_configurations_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::AchievementConfiguration::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_draft_description_init(request: &mut api::AchievementConfiguration) { + request_draft_init(request); + if request.draft.as_mut().unwrap().description.is_none() { + request.draft.as_mut().unwrap().description = Some(Default::default()); + } + } + + fn request_draft_init(request: &mut api::AchievementConfiguration) { + if request.draft.is_none() { + request.draft = Some(Default::default()); + } + } + + fn request_draft_name_init(request: &mut api::AchievementConfiguration) { + request_draft_init(request); + if request.draft.as_mut().unwrap().name.is_none() { + request.draft.as_mut().unwrap().name = Some(Default::default()); + } + } + + fn request_published_description_init(request: &mut api::AchievementConfiguration) { + request_published_init(request); + if request.published.as_mut().unwrap().description.is_none() { + request.published.as_mut().unwrap().description = Some(Default::default()); + } + } + + fn request_published_init(request: &mut api::AchievementConfiguration) { + if request.published.is_none() { + request.published = Some(Default::default()); + } + } + + fn request_published_name_init(request: &mut api::AchievementConfiguration) { + request_published_init(request); + if request.published.as_mut().unwrap().name.is_none() { + request.published.as_mut().unwrap().name = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "achievement-type" => { + request.achievement_type = Some(value.unwrap_or("").to_string()); + }, + "steps-to-unlock" => { + request.steps_to_unlock = Some(arg_from_str(value.unwrap_or("-0"), err, "steps-to-unlock", "integer")); + }, + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "initial-state" => { + request.initial_state = Some(value.unwrap_or("").to_string()); + }, + "token" => { + request.token = Some(value.unwrap_or("").to_string()); + }, + "draft.kind" => { + request_draft_init(&mut request); + request.draft.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "draft.description.kind" => { + request_draft_description_init(&mut request); + request.draft.as_mut().unwrap().description.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "draft.icon-url" => { + request_draft_description_init(&mut request); + request.draft.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); + }, + "draft.point-value" => { + request_draft_description_init(&mut request); + request.draft.as_mut().unwrap().point_value = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.point-value", "integer")); + }, + "draft.sort-rank" => { + request_draft_description_init(&mut request); + request.draft.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.sort-rank", "integer")); + }, + "draft.name.kind" => { + request_draft_name_init(&mut request); + request.draft.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.kind" => { + request_published_init(&mut request); + request.published.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.description.kind" => { + request_published_description_init(&mut request); + request.published.as_mut().unwrap().description.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.icon-url" => { + request_published_description_init(&mut request); + request.published.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); + }, + "published.point-value" => { + request_published_description_init(&mut request); + request.published.as_mut().unwrap().point_value = Some(arg_from_str(value.unwrap_or("-0"), err, "published.point-value", "integer")); + }, + "published.sort-rank" => { + request_published_description_init(&mut request); + request.published.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "published.sort-rank", "integer")); + }, + "published.name.kind" => { + request_published_name_init(&mut request); + request.published.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_published_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["achievement-type", "description", "draft", "icon-url", "id", "initial-state", "kind", "name", "point-value", "published", "sort-rank", "steps-to-unlock", "token"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.achievement_configurations().update(request, opt.value_of("achievement-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _image_configurations_upload(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.image_configurations().upload(opt.value_of("resource-id").unwrap_or(""), opt.value_of("image-type").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _leaderboard_configurations_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.leaderboard_configurations().delete(opt.value_of("leaderboard-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _leaderboard_configurations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.leaderboard_configurations().get(opt.value_of("leaderboard-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _leaderboard_configurations_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::LeaderboardConfiguration::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1551,60 +1166,121 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["currency-code", "draft", "few", "icon-url", "id", "kind", "many", "name", "num-decimal-places", "number-format-type", "one", "other", "published", "score-format", "score-max", "score-min", "score-order", "sort-rank", "suffix", "token", "two", "zero"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.leaderboard_configurations().patch(request, &self.opt.arg_leaderboard_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.leaderboard_configurations().insert(request, opt.value_of("application-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _leaderboard_configurations_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _leaderboard_configurations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.leaderboard_configurations().list(opt.value_of("application-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + "page-token" => { + call = call.page_token(value.unwrap_or("")); + }, + "max-results" => { + call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); + }, + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _leaderboard_configurations_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::LeaderboardConfiguration::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1881,115 +1557,482 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["currency-code", "draft", "few", "icon-url", "id", "kind", "many", "name", "num-decimal-places", "number-format-type", "one", "other", "published", "score-format", "score-max", "score-min", "score-order", "sort-rank", "suffix", "token", "two", "zero"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.leaderboard_configurations().update(request, &self.opt.arg_leaderboard_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.leaderboard_configurations().patch(request, opt.value_of("leaderboard-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _leaderboard_configurations_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::LeaderboardConfiguration::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_draft_init(request: &mut api::LeaderboardConfiguration) { + if request.draft.is_none() { + request.draft = Some(Default::default()); + } + } + + fn request_draft_name_init(request: &mut api::LeaderboardConfiguration) { + request_draft_init(request); + if request.draft.as_mut().unwrap().name.is_none() { + request.draft.as_mut().unwrap().name = Some(Default::default()); + } + } + + fn request_draft_score_format_init(request: &mut api::LeaderboardConfiguration) { + request_draft_init(request); + if request.draft.as_mut().unwrap().score_format.is_none() { + request.draft.as_mut().unwrap().score_format = Some(Default::default()); + } + } + + fn request_draft_score_format_suffix_few_init(request: &mut api::LeaderboardConfiguration) { + request_draft_score_format_suffix_init(request); + if request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().few.is_none() { + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().few = Some(Default::default()); + } + } + + fn request_draft_score_format_suffix_init(request: &mut api::LeaderboardConfiguration) { + request_draft_score_format_init(request); + if request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.is_none() { + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix = Some(Default::default()); + } + } + + fn request_draft_score_format_suffix_many_init(request: &mut api::LeaderboardConfiguration) { + request_draft_score_format_suffix_init(request); + if request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().many.is_none() { + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().many = Some(Default::default()); + } + } + + fn request_draft_score_format_suffix_one_init(request: &mut api::LeaderboardConfiguration) { + request_draft_score_format_suffix_init(request); + if request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().one.is_none() { + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().one = Some(Default::default()); + } + } + + fn request_draft_score_format_suffix_other_init(request: &mut api::LeaderboardConfiguration) { + request_draft_score_format_suffix_init(request); + if request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().other.is_none() { + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().other = Some(Default::default()); + } + } + + fn request_draft_score_format_suffix_two_init(request: &mut api::LeaderboardConfiguration) { + request_draft_score_format_suffix_init(request); + if request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().two.is_none() { + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().two = Some(Default::default()); + } + } + + fn request_draft_score_format_suffix_zero_init(request: &mut api::LeaderboardConfiguration) { + request_draft_score_format_suffix_init(request); + if request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().zero.is_none() { + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().zero = Some(Default::default()); + } + } + + fn request_published_init(request: &mut api::LeaderboardConfiguration) { + if request.published.is_none() { + request.published = Some(Default::default()); + } + } + + fn request_published_name_init(request: &mut api::LeaderboardConfiguration) { + request_published_init(request); + if request.published.as_mut().unwrap().name.is_none() { + request.published.as_mut().unwrap().name = Some(Default::default()); + } + } + + fn request_published_score_format_init(request: &mut api::LeaderboardConfiguration) { + request_published_init(request); + if request.published.as_mut().unwrap().score_format.is_none() { + request.published.as_mut().unwrap().score_format = Some(Default::default()); + } + } + + fn request_published_score_format_suffix_few_init(request: &mut api::LeaderboardConfiguration) { + request_published_score_format_suffix_init(request); + if request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().few.is_none() { + request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().few = Some(Default::default()); + } + } + + fn request_published_score_format_suffix_init(request: &mut api::LeaderboardConfiguration) { + request_published_score_format_init(request); + if request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.is_none() { + request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix = Some(Default::default()); + } + } + + fn request_published_score_format_suffix_many_init(request: &mut api::LeaderboardConfiguration) { + request_published_score_format_suffix_init(request); + if request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().many.is_none() { + request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().many = Some(Default::default()); + } + } + + fn request_published_score_format_suffix_one_init(request: &mut api::LeaderboardConfiguration) { + request_published_score_format_suffix_init(request); + if request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().one.is_none() { + request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().one = Some(Default::default()); + } + } + + fn request_published_score_format_suffix_other_init(request: &mut api::LeaderboardConfiguration) { + request_published_score_format_suffix_init(request); + if request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().other.is_none() { + request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().other = Some(Default::default()); + } + } + + fn request_published_score_format_suffix_two_init(request: &mut api::LeaderboardConfiguration) { + request_published_score_format_suffix_init(request); + if request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().two.is_none() { + request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().two = Some(Default::default()); + } + } + + fn request_published_score_format_suffix_zero_init(request: &mut api::LeaderboardConfiguration) { + request_published_score_format_suffix_init(request); + if request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().zero.is_none() { + request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().zero = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "kind" => { + request.kind = Some(value.unwrap_or("").to_string()); + }, + "score-order" => { + request.score_order = Some(value.unwrap_or("").to_string()); + }, + "score-min" => { + request.score_min = Some(value.unwrap_or("").to_string()); + }, + "token" => { + request.token = Some(value.unwrap_or("").to_string()); + }, + "score-max" => { + request.score_max = Some(value.unwrap_or("").to_string()); + }, + "published.score-format.currency-code" => { + request_published_score_format_init(&mut request); + request.published.as_mut().unwrap().score_format.as_mut().unwrap().currency_code = Some(value.unwrap_or("").to_string()); + }, + "published.score-format.suffix.many.kind" => { + request_published_score_format_suffix_many_init(&mut request); + request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().many.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.score-format.suffix.two.kind" => { + request_published_score_format_suffix_two_init(&mut request); + request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().two.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.score-format.suffix.one.kind" => { + request_published_score_format_suffix_one_init(&mut request); + request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().one.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.score-format.suffix.few.kind" => { + request_published_score_format_suffix_few_init(&mut request); + request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().few.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.score-format.suffix.zero.kind" => { + request_published_score_format_suffix_zero_init(&mut request); + request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().zero.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.score-format.suffix.other.kind" => { + request_published_score_format_suffix_other_init(&mut request); + request.published.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().other.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.score-format.number-format-type" => { + request_published_score_format_suffix_init(&mut request); + request.published.as_mut().unwrap().score_format.as_mut().unwrap().number_format_type = Some(value.unwrap_or("").to_string()); + }, + "published.score-format.num-decimal-places" => { + request_published_score_format_suffix_init(&mut request); + request.published.as_mut().unwrap().score_format.as_mut().unwrap().num_decimal_places = Some(arg_from_str(value.unwrap_or("-0"), err, "published.score-format.num-decimal-places", "integer")); + }, + "published.icon-url" => { + request_published_score_format_init(&mut request); + request.published.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); + }, + "published.kind" => { + request_published_score_format_init(&mut request); + request.published.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.name.kind" => { + request_published_name_init(&mut request); + request.published.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "published.sort-rank" => { + request_published_name_init(&mut request); + request.published.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "published.sort-rank", "integer")); + }, + "draft.score-format.currency-code" => { + request_draft_score_format_init(&mut request); + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().currency_code = Some(value.unwrap_or("").to_string()); + }, + "draft.score-format.suffix.many.kind" => { + request_draft_score_format_suffix_many_init(&mut request); + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().many.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "draft.score-format.suffix.two.kind" => { + request_draft_score_format_suffix_two_init(&mut request); + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().two.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "draft.score-format.suffix.one.kind" => { + request_draft_score_format_suffix_one_init(&mut request); + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().one.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "draft.score-format.suffix.few.kind" => { + request_draft_score_format_suffix_few_init(&mut request); + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().few.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "draft.score-format.suffix.zero.kind" => { + request_draft_score_format_suffix_zero_init(&mut request); + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().zero.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "draft.score-format.suffix.other.kind" => { + request_draft_score_format_suffix_other_init(&mut request); + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().suffix.as_mut().unwrap().other.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "draft.score-format.number-format-type" => { + request_draft_score_format_suffix_init(&mut request); + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().number_format_type = Some(value.unwrap_or("").to_string()); + }, + "draft.score-format.num-decimal-places" => { + request_draft_score_format_suffix_init(&mut request); + request.draft.as_mut().unwrap().score_format.as_mut().unwrap().num_decimal_places = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.score-format.num-decimal-places", "integer")); + }, + "draft.icon-url" => { + request_draft_score_format_init(&mut request); + request.draft.as_mut().unwrap().icon_url = Some(value.unwrap_or("").to_string()); + }, + "draft.kind" => { + request_draft_score_format_init(&mut request); + request.draft.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "draft.name.kind" => { + request_draft_name_init(&mut request); + request.draft.as_mut().unwrap().name.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "draft.sort-rank" => { + request_draft_name_init(&mut request); + request.draft.as_mut().unwrap().sort_rank = Some(arg_from_str(value.unwrap_or("-0"), err, "draft.sort-rank", "integer")); + }, + "id" => { + request_draft_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["currency-code", "draft", "few", "icon-url", "id", "kind", "many", "name", "num-decimal-places", "number-format-type", "one", "other", "published", "score-format", "score-max", "score-min", "score-order", "sort-rank", "suffix", "token", "two", "zero"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.leaderboard_configurations().update(request, opt.value_of("leaderboard-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_achievement_configurations { - if self.opt.cmd_delete { - call_result = self._achievement_configurations_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._achievement_configurations_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._achievement_configurations_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._achievement_configurations_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._achievement_configurations_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._achievement_configurations_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("achievement-configurations", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._achievement_configurations_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._achievement_configurations_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._achievement_configurations_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._achievement_configurations_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._achievement_configurations_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._achievement_configurations_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("achievement-configurations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("image-configurations", Some(opt)) => { + match opt.subcommand() { + ("upload", Some(opt)) => { + call_result = self._image_configurations_upload(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("image-configurations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("leaderboard-configurations", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._leaderboard_configurations_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._leaderboard_configurations_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._leaderboard_configurations_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._leaderboard_configurations_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._leaderboard_configurations_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._leaderboard_configurations_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("leaderboard-configurations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_image_configurations { - if self.opt.cmd_upload { - call_result = self._image_configurations_upload(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_leaderboard_configurations { - if self.opt.cmd_delete { - call_result = self._leaderboard_configurations_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._leaderboard_configurations_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._leaderboard_configurations_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._leaderboard_configurations_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._leaderboard_configurations_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._leaderboard_configurations_update(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -2002,7 +2045,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2015,7 +2058,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2025,37 +2068,466 @@ impl Engine { let engine = Engine { opt: opt, hub: api::GamesConfiguration::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let upload_value_names = ["mode", "file"]; + let arg_data = [ + ("achievement-configurations", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Delete the achievement configuration with the given ID."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/achievement-configurations_delete", + vec![ + (Some(r##"achievement-id"##), + None, + Some(r##"The ID of the achievement used by this method."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves the metadata of the achievement configuration with the given ID."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/achievement-configurations_get", + vec![ + (Some(r##"achievement-id"##), + None, + Some(r##"The ID of the achievement used by this method."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Insert a new achievement configuration in this application."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/achievement-configurations_insert", + vec![ + (Some(r##"application-id"##), + None, + Some(r##"The application ID from the Google Play developer console."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Returns a list of the achievement configurations in this application."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/achievement-configurations_list", + vec![ + (Some(r##"application-id"##), + None, + Some(r##"The application ID from the Google Play developer console."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update the metadata of the achievement configuration with the given ID. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/achievement-configurations_patch", + vec![ + (Some(r##"achievement-id"##), + None, + Some(r##"The ID of the achievement used by this method."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update the metadata of the achievement configuration with the given ID."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/achievement-configurations_update", + vec![ + (Some(r##"achievement-id"##), + None, + Some(r##"The ID of the achievement used by this method."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("image-configurations", "methods: 'upload'", vec![ + ("upload", + Some(r##"Uploads an image for a resource with the given ID and image type."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/image-configurations_upload", + vec![ + (Some(r##"resource-id"##), + None, + Some(r##"The ID of the resource used by this method."##), + Some(true), + Some(false)), + + (Some(r##"image-type"##), + None, + Some(r##"Selects which image in a resource for this method."##), + Some(true), + Some(false)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("leaderboard-configurations", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Delete the leaderboard configuration with the given ID."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/leaderboard-configurations_delete", + vec![ + (Some(r##"leaderboard-id"##), + None, + Some(r##"The ID of the leaderboard."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves the metadata of the leaderboard configuration with the given ID."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/leaderboard-configurations_get", + vec![ + (Some(r##"leaderboard-id"##), + None, + Some(r##"The ID of the leaderboard."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Insert a new leaderboard configuration in this application."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/leaderboard-configurations_insert", + vec![ + (Some(r##"application-id"##), + None, + Some(r##"The application ID from the Google Play developer console."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Returns a list of the leaderboard configurations in this application."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/leaderboard-configurations_list", + vec![ + (Some(r##"application-id"##), + None, + Some(r##"The application ID from the Google Play developer console."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update the metadata of the leaderboard configuration with the given ID. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/leaderboard-configurations_patch", + vec![ + (Some(r##"leaderboard-id"##), + None, + Some(r##"The ID of the leaderboard."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update the metadata of the leaderboard configuration with the given ID."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli/leaderboard-configurations_update", + vec![ + (Some(r##"leaderboard-id"##), + None, + Some(r##"The ID of the leaderboard."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("gamesconfiguration1-configuration") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150413") + .about("The Publishing API for Google Play Game Services.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + if arg_name_str == "mode" { + arg = arg.number_of_values(2); + arg = arg.value_names(&upload_value_names); + + scmd = scmd.arg(Arg::with_name("mime") + .short("m") + .requires("mode") + .required(false) + .help("The file's mime time, like 'application/octet-stream'") + .takes_value(true)); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/gamesconfiguration1_configuration/Cargo.toml b/gen/gamesconfiguration1_configuration/Cargo.toml index 6c19e0ddd4..480dd1991d 100644 --- a/gen/gamesconfiguration1_configuration/Cargo.toml +++ b/gen/gamesconfiguration1_configuration/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-gamesconfiguration1_configuration" -version = "0.1.6+20150413" +version = "0.1.7+20150413" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with Games Configuration (protocol v1configuration)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/gamesconfiguration1_configuration" @@ -15,9 +15,10 @@ keywords = ["gamesConfiguration", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/gamesconfiguration1_configuration/README.md b/gen/gamesconfiguration1_configuration/README.md index fe2cb894ca..df141cbe91 100644 --- a/gen/gamesconfiguration1_configuration/README.md +++ b/gen/gamesconfiguration1_configuration/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-gamesconfiguration1_configuration` library allows access to all features of the *Google Games Configuration* service. -This documentation was generated from *Games Configuration* crate version *0.1.6+20150413*, where *20150413* is the exact revision of the *gamesConfiguration:v1configuration* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *Games Configuration* crate version *0.1.7+20150413*, where *20150413* is the exact revision of the *gamesConfiguration:v1configuration* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *Games Configuration* *v1_configuration* API can be found at the [official documentation site](https://developers.google.com/games/services). @@ -172,7 +172,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_gamesconfiguration1_configuration/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/gamesconfiguration1_configuration/src/cmn.rs b/gen/gamesconfiguration1_configuration/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/gamesconfiguration1_configuration/src/cmn.rs +++ b/gen/gamesconfiguration1_configuration/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/gamesconfiguration1_configuration/src/lib.rs b/gen/gamesconfiguration1_configuration/src/lib.rs index aec6f9cd9d..8d4ffa8b2e 100644 --- a/gen/gamesconfiguration1_configuration/src/lib.rs +++ b/gen/gamesconfiguration1_configuration/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *Games Configuration* crate version *0.1.6+20150413*, where *20150413* is the exact revision of the *gamesConfiguration:v1configuration* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *Games Configuration* crate version *0.1.7+20150413*, where *20150413* is the exact revision of the *gamesConfiguration:v1configuration* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *Games Configuration* *v1_configuration* API can be found at the //! [official documentation site](https://developers.google.com/games/services). @@ -173,7 +173,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -182,7 +182,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -198,6 +197,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -316,7 +316,7 @@ impl<'a, C, A> GamesConfiguration<C, A> GamesConfiguration { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -331,7 +331,7 @@ impl<'a, C, A> GamesConfiguration<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1130,7 +1130,7 @@ impl<'a, C, A> ImageConfigurationUploadCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1168,7 +1168,7 @@ impl<'a, C, A> ImageConfigurationUploadCall<'a, C, A> where C: BorrowMut<hyper:: response } else { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); if protocol == "simple" { @@ -1226,7 +1226,7 @@ impl<'a, C, A> ImageConfigurationUploadCall<'a, C, A> where C: BorrowMut<hyper:: let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -1254,6 +1254,7 @@ impl<'a, C, A> ImageConfigurationUploadCall<'a, C, A> where C: BorrowMut<hyper:: Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -1490,7 +1491,7 @@ impl<'a, C, A> AchievementConfigurationListCall<'a, C, A> where C: BorrowMut<hyp if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1512,7 +1513,7 @@ impl<'a, C, A> AchievementConfigurationListCall<'a, C, A> where C: BorrowMut<hyp access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1695,6 +1696,7 @@ impl<'a, C, A> AchievementConfigurationUpdateCall<'a, C, A> where C: BorrowMut<h /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AchievementConfiguration)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1750,11 +1752,20 @@ impl<'a, C, A> AchievementConfigurationUpdateCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1777,7 +1788,7 @@ impl<'a, C, A> AchievementConfigurationUpdateCall<'a, C, A> where C: BorrowMut<h request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1958,6 +1969,7 @@ impl<'a, C, A> AchievementConfigurationInsertCall<'a, C, A> where C: BorrowMut<h /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AchievementConfiguration)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2013,11 +2025,20 @@ impl<'a, C, A> AchievementConfigurationInsertCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2040,7 +2061,7 @@ impl<'a, C, A> AchievementConfigurationInsertCall<'a, C, A> where C: BorrowMut<h request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2269,7 +2290,7 @@ impl<'a, C, A> AchievementConfigurationGetCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2291,7 +2312,7 @@ impl<'a, C, A> AchievementConfigurationGetCall<'a, C, A> where C: BorrowMut<hype access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2460,6 +2481,7 @@ impl<'a, C, A> AchievementConfigurationPatchCall<'a, C, A> where C: BorrowMut<hy /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AchievementConfiguration)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2515,11 +2537,20 @@ impl<'a, C, A> AchievementConfigurationPatchCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2542,7 +2573,7 @@ impl<'a, C, A> AchievementConfigurationPatchCall<'a, C, A> where C: BorrowMut<hy request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2770,7 +2801,7 @@ impl<'a, C, A> AchievementConfigurationDeleteCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2792,7 +2823,7 @@ impl<'a, C, A> AchievementConfigurationDeleteCall<'a, C, A> where C: BorrowMut<h access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2951,6 +2982,7 @@ impl<'a, C, A> LeaderboardConfigurationInsertCall<'a, C, A> where C: BorrowMut<h /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LeaderboardConfiguration)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3006,11 +3038,20 @@ impl<'a, C, A> LeaderboardConfigurationInsertCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3033,7 +3074,7 @@ impl<'a, C, A> LeaderboardConfigurationInsertCall<'a, C, A> where C: BorrowMut<h request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3262,7 +3303,7 @@ impl<'a, C, A> LeaderboardConfigurationGetCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3284,7 +3325,7 @@ impl<'a, C, A> LeaderboardConfigurationGetCall<'a, C, A> where C: BorrowMut<hype access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3453,6 +3494,7 @@ impl<'a, C, A> LeaderboardConfigurationPatchCall<'a, C, A> where C: BorrowMut<hy /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LeaderboardConfiguration)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3508,11 +3550,20 @@ impl<'a, C, A> LeaderboardConfigurationPatchCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3535,7 +3586,7 @@ impl<'a, C, A> LeaderboardConfigurationPatchCall<'a, C, A> where C: BorrowMut<hy request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3716,6 +3767,7 @@ impl<'a, C, A> LeaderboardConfigurationUpdateCall<'a, C, A> where C: BorrowMut<h /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LeaderboardConfiguration)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3771,11 +3823,20 @@ impl<'a, C, A> LeaderboardConfigurationUpdateCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3798,7 +3859,7 @@ impl<'a, C, A> LeaderboardConfigurationUpdateCall<'a, C, A> where C: BorrowMut<h request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4037,7 +4098,7 @@ impl<'a, C, A> LeaderboardConfigurationListCall<'a, C, A> where C: BorrowMut<hyp if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4059,7 +4120,7 @@ impl<'a, C, A> LeaderboardConfigurationListCall<'a, C, A> where C: BorrowMut<hyp access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4289,7 +4350,7 @@ impl<'a, C, A> LeaderboardConfigurationDeleteCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4311,7 +4372,7 @@ impl<'a, C, A> LeaderboardConfigurationDeleteCall<'a, C, A> where C: BorrowMut<h access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/gamesmanagement1_management-cli/Cargo.toml b/gen/gamesmanagement1_management-cli/Cargo.toml index 3fd2facf84..94993e1b3a 100644 --- a/gen/gamesmanagement1_management-cli/Cargo.toml +++ b/gen/gamesmanagement1_management-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-gamesmanagement1_management-cli" -version = "0.1.0+20150413" +version = "0.2.0+20150413" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with Games Management (protocol v1management)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/gamesmanagement1_management-cli" @@ -17,15 +17,14 @@ keywords = ["gamesManagement", "google", "cli"] name = "gamesmanagement1-management" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-gamesmanagement1_management] path = "../gamesmanagement1_management" diff --git a/gen/gamesmanagement1_management-cli/README.md b/gen/gamesmanagement1_management-cli/README.md index 6630c38858..9da1eb9cab 100644 --- a/gen/gamesmanagement1_management-cli/README.md +++ b/gen/gamesmanagement1_management-cli/README.md @@ -10,47 +10,56 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *Games Management* API can be found at the +[official documentation site](https://developers.google.com/games/services). + # Usage -This documentation was generated from the *Games Management* API at revision *20150413*. The CLI is at version *0.1.0*. +This documentation was generated from the *Games Management* API at revision *20150413*. The CLI is at version *0.2.0*. ```bash - gamesmanagement1-management [options] achievements reset <achievement-id> [-p <v>...] [-o <out>] - gamesmanagement1-management [options] achievements reset-all [-p <v>...] [-o <out>] - gamesmanagement1-management [options] achievements reset-all-for-all-players [-p <v>...] - gamesmanagement1-management [options] achievements reset-for-all-players <achievement-id> [-p <v>...] - gamesmanagement1-management [options] achievements reset-multiple-for-all-players -r <kv>... [-p <v>...] - gamesmanagement1-management [options] applications list-hidden <application-id> [-p <v>...] [-o <out>] - gamesmanagement1-management [options] events reset <event-id> [-p <v>...] - gamesmanagement1-management [options] events reset-all [-p <v>...] - gamesmanagement1-management [options] events reset-all-for-all-players [-p <v>...] - gamesmanagement1-management [options] events reset-for-all-players <event-id> [-p <v>...] - gamesmanagement1-management [options] events reset-multiple-for-all-players -r <kv>... [-p <v>...] - gamesmanagement1-management [options] players hide <application-id> <player-id> [-p <v>...] - gamesmanagement1-management [options] players unhide <application-id> <player-id> [-p <v>...] - gamesmanagement1-management [options] quests reset <quest-id> [-p <v>...] - gamesmanagement1-management [options] quests reset-all [-p <v>...] - gamesmanagement1-management [options] quests reset-all-for-all-players [-p <v>...] - gamesmanagement1-management [options] quests reset-for-all-players <quest-id> [-p <v>...] - gamesmanagement1-management [options] quests reset-multiple-for-all-players -r <kv>... [-p <v>...] - gamesmanagement1-management [options] rooms reset [-p <v>...] - gamesmanagement1-management [options] rooms reset-for-all-players [-p <v>...] - gamesmanagement1-management [options] scores reset <leaderboard-id> [-p <v>...] [-o <out>] - gamesmanagement1-management [options] scores reset-all [-p <v>...] [-o <out>] - gamesmanagement1-management [options] scores reset-all-for-all-players [-p <v>...] - gamesmanagement1-management [options] scores reset-for-all-players <leaderboard-id> [-p <v>...] - gamesmanagement1-management [options] scores reset-multiple-for-all-players -r <kv>... [-p <v>...] - gamesmanagement1-management [options] turn-based-matches reset [-p <v>...] - gamesmanagement1-management [options] turn-based-matches reset-for-all-players [-p <v>...] +gamesmanagement1-management [options] + achievements + reset <achievement-id> [-p <v>]... [-o <out>] + reset-all [-p <v>]... [-o <out>] + reset-all-for-all-players [-p <v>]... + reset-for-all-players <achievement-id> [-p <v>]... + reset-multiple-for-all-players (-r <kv>)... [-p <v>]... + applications + list-hidden <application-id> [-p <v>]... [-o <out>] + events + reset <event-id> [-p <v>]... + reset-all [-p <v>]... + reset-all-for-all-players [-p <v>]... + reset-for-all-players <event-id> [-p <v>]... + reset-multiple-for-all-players (-r <kv>)... [-p <v>]... + players + hide <application-id> <player-id> [-p <v>]... + unhide <application-id> <player-id> [-p <v>]... + quests + reset <quest-id> [-p <v>]... + reset-all [-p <v>]... + reset-all-for-all-players [-p <v>]... + reset-for-all-players <quest-id> [-p <v>]... + reset-multiple-for-all-players (-r <kv>)... [-p <v>]... + rooms + reset [-p <v>]... + reset-for-all-players [-p <v>]... + scores + reset <leaderboard-id> [-p <v>]... [-o <out>] + reset-all [-p <v>]... [-o <out>] + reset-all-for-all-players [-p <v>]... + reset-for-all-players <leaderboard-id> [-p <v>]... + reset-multiple-for-all-players (-r <kv>)... [-p <v>]... + turn-based-matches + reset [-p <v>]... + reset-for-all-players [-p <v>]... gamesmanagement1-management --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/gamesmanagement1_management-cli/mkdocs.yml b/gen/gamesmanagement1_management-cli/mkdocs.yml index e88a6879ef..35ae14a661 100644 --- a/gen/gamesmanagement1_management-cli/mkdocs.yml +++ b/gen/gamesmanagement1_management-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Games Management v0.1.0+20150413 +site_name: Games Management v0.2.0+20150413 site_url: http://byron.github.io/google-apis-rs/google-gamesmanagement1_management-cli site_description: Write integrating applications with bcore diff --git a/gen/gamesmanagement1_management-cli/src/cmn.rs b/gen/gamesmanagement1_management-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/gamesmanagement1_management-cli/src/cmn.rs +++ b/gen/gamesmanagement1_management-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/gamesmanagement1_management-cli/src/main.rs b/gen/gamesmanagement1_management-cli/src/main.rs index 4d5aa82208..dcc21b56b9 100644 --- a/gen/gamesmanagement1_management-cli/src/main.rs +++ b/gen/gamesmanagement1_management-cli/src/main.rs @@ -2,275 +2,241 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_gamesmanagement1_management as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - gamesmanagement1-management [options] achievements reset <achievement-id> [-p <v>...] [-o <out>] - gamesmanagement1-management [options] achievements reset-all [-p <v>...] [-o <out>] - gamesmanagement1-management [options] achievements reset-all-for-all-players [-p <v>...] - gamesmanagement1-management [options] achievements reset-for-all-players <achievement-id> [-p <v>...] - gamesmanagement1-management [options] achievements reset-multiple-for-all-players -r <kv>... [-p <v>...] - gamesmanagement1-management [options] applications list-hidden <application-id> [-p <v>...] [-o <out>] - gamesmanagement1-management [options] events reset <event-id> [-p <v>...] - gamesmanagement1-management [options] events reset-all [-p <v>...] - gamesmanagement1-management [options] events reset-all-for-all-players [-p <v>...] - gamesmanagement1-management [options] events reset-for-all-players <event-id> [-p <v>...] - gamesmanagement1-management [options] events reset-multiple-for-all-players -r <kv>... [-p <v>...] - gamesmanagement1-management [options] players hide <application-id> <player-id> [-p <v>...] - gamesmanagement1-management [options] players unhide <application-id> <player-id> [-p <v>...] - gamesmanagement1-management [options] quests reset <quest-id> [-p <v>...] - gamesmanagement1-management [options] quests reset-all [-p <v>...] - gamesmanagement1-management [options] quests reset-all-for-all-players [-p <v>...] - gamesmanagement1-management [options] quests reset-for-all-players <quest-id> [-p <v>...] - gamesmanagement1-management [options] quests reset-multiple-for-all-players -r <kv>... [-p <v>...] - gamesmanagement1-management [options] rooms reset [-p <v>...] - gamesmanagement1-management [options] rooms reset-for-all-players [-p <v>...] - gamesmanagement1-management [options] scores reset <leaderboard-id> [-p <v>...] [-o <out>] - gamesmanagement1-management [options] scores reset-all [-p <v>...] [-o <out>] - gamesmanagement1-management [options] scores reset-all-for-all-players [-p <v>...] - gamesmanagement1-management [options] scores reset-for-all-players <leaderboard-id> [-p <v>...] - gamesmanagement1-management [options] scores reset-multiple-for-all-players -r <kv>... [-p <v>...] - gamesmanagement1-management [options] turn-based-matches reset [-p <v>...] - gamesmanagement1-management [options] turn-based-matches reset-for-all-players [-p <v>...] - gamesmanagement1-management --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::GamesManagement<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _achievements_reset(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.achievements().reset(&self.opt.arg_achievement_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _achievements_reset(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.achievements().reset(opt.value_of("achievement-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _achievements_reset_all(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _achievements_reset_all(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.achievements().reset_all(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _achievements_reset_all_for_all_players(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _achievements_reset_all_for_all_players(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.achievements().reset_all_for_all_players(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _achievements_reset_for_all_players(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.achievements().reset_for_all_players(&self.opt.arg_achievement_id); - for parg in self.opt.arg_v.iter() { + fn _achievements_reset_for_all_players(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.achievements().reset_for_all_players(opt.value_of("achievement-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _achievements_reset_multiple_for_all_players(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _achievements_reset_multiple_for_all_players(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AchievementResetMultipleForAllRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -295,56 +261,56 @@ impl Engine { request.kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["achievement-ids", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.achievements().reset_multiple_for_all_players(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _applications_list_hidden(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.applications().list_hidden(&self.opt.arg_application_id); - for parg in self.opt.arg_v.iter() { + fn _applications_list_hidden(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.applications().list_hidden(opt.value_of("application-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -353,228 +319,228 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _events_reset(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.events().reset(&self.opt.arg_event_id); - for parg in self.opt.arg_v.iter() { + fn _events_reset(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.events().reset(opt.value_of("event-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _events_reset_all(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _events_reset_all(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.events().reset_all(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _events_reset_all_for_all_players(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _events_reset_all_for_all_players(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.events().reset_all_for_all_players(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _events_reset_for_all_players(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.events().reset_for_all_players(&self.opt.arg_event_id); - for parg in self.opt.arg_v.iter() { + fn _events_reset_for_all_players(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.events().reset_for_all_players(opt.value_of("event-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _events_reset_multiple_for_all_players(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _events_reset_multiple_for_all_players(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::EventsResetMultipleForAllRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -599,322 +565,316 @@ impl Engine { request.kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["event-ids", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.events().reset_multiple_for_all_players(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _players_hide(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.players().hide(&self.opt.arg_application_id, &self.opt.arg_player_id); - for parg in self.opt.arg_v.iter() { + fn _players_hide(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.players().hide(opt.value_of("application-id").unwrap_or(""), opt.value_of("player-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _players_unhide(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.players().unhide(&self.opt.arg_application_id, &self.opt.arg_player_id); - for parg in self.opt.arg_v.iter() { + fn _players_unhide(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.players().unhide(opt.value_of("application-id").unwrap_or(""), opt.value_of("player-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _quests_reset(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.quests().reset(&self.opt.arg_quest_id); - for parg in self.opt.arg_v.iter() { + fn _quests_reset(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.quests().reset(opt.value_of("quest-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _quests_reset_all(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _quests_reset_all(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.quests().reset_all(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _quests_reset_all_for_all_players(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _quests_reset_all_for_all_players(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.quests().reset_all_for_all_players(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _quests_reset_for_all_players(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.quests().reset_for_all_players(&self.opt.arg_quest_id); - for parg in self.opt.arg_v.iter() { + fn _quests_reset_for_all_players(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.quests().reset_for_all_players(opt.value_of("quest-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _quests_reset_multiple_for_all_players(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _quests_reset_multiple_for_all_players(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::QuestsResetMultipleForAllRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -939,326 +899,330 @@ impl Engine { request.kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind", "quest-ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.quests().reset_multiple_for_all_players(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _rooms_reset(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _rooms_reset(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.rooms().reset(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _rooms_reset_for_all_players(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _rooms_reset_for_all_players(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.rooms().reset_for_all_players(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _scores_reset(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.scores().reset(&self.opt.arg_leaderboard_id); - for parg in self.opt.arg_v.iter() { + fn _scores_reset(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.scores().reset(opt.value_of("leaderboard-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _scores_reset_all(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _scores_reset_all(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.scores().reset_all(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _scores_reset_all_for_all_players(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _scores_reset_all_for_all_players(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.scores().reset_all_for_all_players(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _scores_reset_for_all_players(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.scores().reset_for_all_players(&self.opt.arg_leaderboard_id); - for parg in self.opt.arg_v.iter() { + fn _scores_reset_for_all_players(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.scores().reset_for_all_players(opt.value_of("leaderboard-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _scores_reset_multiple_for_all_players(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _scores_reset_multiple_for_all_players(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ScoresResetMultipleForAllRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1283,254 +1247,308 @@ impl Engine { request.kind = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind", "leaderboard-ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.scores().reset_multiple_for_all_players(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _turn_based_matches_reset(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _turn_based_matches_reset(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.turn_based_matches().reset(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _turn_based_matches_reset_for_all_players(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _turn_based_matches_reset_for_all_players(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.turn_based_matches().reset_for_all_players(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_achievements { - if self.opt.cmd_reset { - call_result = self._achievements_reset(dry_run, &mut err); - } else if self.opt.cmd_reset_all { - call_result = self._achievements_reset_all(dry_run, &mut err); - } else if self.opt.cmd_reset_all_for_all_players { - call_result = self._achievements_reset_all_for_all_players(dry_run, &mut err); - } else if self.opt.cmd_reset_for_all_players { - call_result = self._achievements_reset_for_all_players(dry_run, &mut err); - } else if self.opt.cmd_reset_multiple_for_all_players { - call_result = self._achievements_reset_multiple_for_all_players(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("achievements", Some(opt)) => { + match opt.subcommand() { + ("reset", Some(opt)) => { + call_result = self._achievements_reset(opt, dry_run, &mut err); + }, + ("reset-all", Some(opt)) => { + call_result = self._achievements_reset_all(opt, dry_run, &mut err); + }, + ("reset-all-for-all-players", Some(opt)) => { + call_result = self._achievements_reset_all_for_all_players(opt, dry_run, &mut err); + }, + ("reset-for-all-players", Some(opt)) => { + call_result = self._achievements_reset_for_all_players(opt, dry_run, &mut err); + }, + ("reset-multiple-for-all-players", Some(opt)) => { + call_result = self._achievements_reset_multiple_for_all_players(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("achievements".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("applications", Some(opt)) => { + match opt.subcommand() { + ("list-hidden", Some(opt)) => { + call_result = self._applications_list_hidden(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("applications".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("events", Some(opt)) => { + match opt.subcommand() { + ("reset", Some(opt)) => { + call_result = self._events_reset(opt, dry_run, &mut err); + }, + ("reset-all", Some(opt)) => { + call_result = self._events_reset_all(opt, dry_run, &mut err); + }, + ("reset-all-for-all-players", Some(opt)) => { + call_result = self._events_reset_all_for_all_players(opt, dry_run, &mut err); + }, + ("reset-for-all-players", Some(opt)) => { + call_result = self._events_reset_for_all_players(opt, dry_run, &mut err); + }, + ("reset-multiple-for-all-players", Some(opt)) => { + call_result = self._events_reset_multiple_for_all_players(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("events".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("players", Some(opt)) => { + match opt.subcommand() { + ("hide", Some(opt)) => { + call_result = self._players_hide(opt, dry_run, &mut err); + }, + ("unhide", Some(opt)) => { + call_result = self._players_unhide(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("players".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("quests", Some(opt)) => { + match opt.subcommand() { + ("reset", Some(opt)) => { + call_result = self._quests_reset(opt, dry_run, &mut err); + }, + ("reset-all", Some(opt)) => { + call_result = self._quests_reset_all(opt, dry_run, &mut err); + }, + ("reset-all-for-all-players", Some(opt)) => { + call_result = self._quests_reset_all_for_all_players(opt, dry_run, &mut err); + }, + ("reset-for-all-players", Some(opt)) => { + call_result = self._quests_reset_for_all_players(opt, dry_run, &mut err); + }, + ("reset-multiple-for-all-players", Some(opt)) => { + call_result = self._quests_reset_multiple_for_all_players(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("quests".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("rooms", Some(opt)) => { + match opt.subcommand() { + ("reset", Some(opt)) => { + call_result = self._rooms_reset(opt, dry_run, &mut err); + }, + ("reset-for-all-players", Some(opt)) => { + call_result = self._rooms_reset_for_all_players(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("rooms".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("scores", Some(opt)) => { + match opt.subcommand() { + ("reset", Some(opt)) => { + call_result = self._scores_reset(opt, dry_run, &mut err); + }, + ("reset-all", Some(opt)) => { + call_result = self._scores_reset_all(opt, dry_run, &mut err); + }, + ("reset-all-for-all-players", Some(opt)) => { + call_result = self._scores_reset_all_for_all_players(opt, dry_run, &mut err); + }, + ("reset-for-all-players", Some(opt)) => { + call_result = self._scores_reset_for_all_players(opt, dry_run, &mut err); + }, + ("reset-multiple-for-all-players", Some(opt)) => { + call_result = self._scores_reset_multiple_for_all_players(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("scores".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("turn-based-matches", Some(opt)) => { + match opt.subcommand() { + ("reset", Some(opt)) => { + call_result = self._turn_based_matches_reset(opt, dry_run, &mut err); + }, + ("reset-for-all-players", Some(opt)) => { + call_result = self._turn_based_matches_reset_for_all_players(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("turn-based-matches".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_applications { - if self.opt.cmd_list_hidden { - call_result = self._applications_list_hidden(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_events { - if self.opt.cmd_reset { - call_result = self._events_reset(dry_run, &mut err); - } else if self.opt.cmd_reset_all { - call_result = self._events_reset_all(dry_run, &mut err); - } else if self.opt.cmd_reset_all_for_all_players { - call_result = self._events_reset_all_for_all_players(dry_run, &mut err); - } else if self.opt.cmd_reset_for_all_players { - call_result = self._events_reset_for_all_players(dry_run, &mut err); - } else if self.opt.cmd_reset_multiple_for_all_players { - call_result = self._events_reset_multiple_for_all_players(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_players { - if self.opt.cmd_hide { - call_result = self._players_hide(dry_run, &mut err); - } else if self.opt.cmd_unhide { - call_result = self._players_unhide(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_quests { - if self.opt.cmd_reset { - call_result = self._quests_reset(dry_run, &mut err); - } else if self.opt.cmd_reset_all { - call_result = self._quests_reset_all(dry_run, &mut err); - } else if self.opt.cmd_reset_all_for_all_players { - call_result = self._quests_reset_all_for_all_players(dry_run, &mut err); - } else if self.opt.cmd_reset_for_all_players { - call_result = self._quests_reset_for_all_players(dry_run, &mut err); - } else if self.opt.cmd_reset_multiple_for_all_players { - call_result = self._quests_reset_multiple_for_all_players(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_rooms { - if self.opt.cmd_reset { - call_result = self._rooms_reset(dry_run, &mut err); - } else if self.opt.cmd_reset_for_all_players { - call_result = self._rooms_reset_for_all_players(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_scores { - if self.opt.cmd_reset { - call_result = self._scores_reset(dry_run, &mut err); - } else if self.opt.cmd_reset_all { - call_result = self._scores_reset_all(dry_run, &mut err); - } else if self.opt.cmd_reset_all_for_all_players { - call_result = self._scores_reset_all_for_all_players(dry_run, &mut err); - } else if self.opt.cmd_reset_for_all_players { - call_result = self._scores_reset_for_all_players(dry_run, &mut err); - } else if self.opt.cmd_reset_multiple_for_all_players { - call_result = self._scores_reset_multiple_for_all_players(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_turn_based_matches { - if self.opt.cmd_reset { - call_result = self._turn_based_matches_reset(dry_run, &mut err); - } else if self.opt.cmd_reset_for_all_players { - call_result = self._turn_based_matches_reset_for_all_players(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -1543,7 +1561,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1556,7 +1574,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1566,37 +1584,549 @@ impl Engine { let engine = Engine { opt: opt, hub: api::GamesManagement::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("achievements", "methods: 'reset', 'reset-all', 'reset-all-for-all-players', 'reset-for-all-players' and 'reset-multiple-for-all-players'", vec![ + ("reset", + Some(r##"Resets the achievement with the given ID for the currently authenticated player. This method is only accessible to whitelisted tester accounts for your application."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/achievements_reset", + vec![ + (Some(r##"achievement-id"##), + None, + Some(r##"The ID of the achievement used by this method."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reset-all", + Some(r##"Resets all achievements for the currently authenticated player for your application. This method is only accessible to whitelisted tester accounts for your application."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/achievements_reset-all", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reset-all-for-all-players", + Some(r##"Resets all draft achievements for all players. This method is only available to user accounts for your developer console."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/achievements_reset-all-for-all-players", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("reset-for-all-players", + Some(r##"Resets the achievement with the given ID for all players. This method is only available to user accounts for your developer console. Only draft achievements can be reset."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/achievements_reset-for-all-players", + vec![ + (Some(r##"achievement-id"##), + None, + Some(r##"The ID of the achievement used by this method."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("reset-multiple-for-all-players", + Some(r##"Resets achievements with the given IDs for all players. This method is only available to user accounts for your developer console. Only draft achievements may be reset."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/achievements_reset-multiple-for-all-players", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("applications", "methods: 'list-hidden'", vec![ + ("list-hidden", + Some(r##"Get the list of players hidden from the given application. This method is only available to user accounts for your developer console."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/applications_list-hidden", + vec![ + (Some(r##"application-id"##), + None, + Some(r##"The application ID from the Google Play developer console."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("events", "methods: 'reset', 'reset-all', 'reset-all-for-all-players', 'reset-for-all-players' and 'reset-multiple-for-all-players'", vec![ + ("reset", + Some(r##"Resets all player progress on the event with the given ID for the currently authenticated player. This method is only accessible to whitelisted tester accounts for your application. All quests for this player that use the event will also be reset."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/events_reset", + vec![ + (Some(r##"event-id"##), + None, + Some(r##"The ID of the event."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("reset-all", + Some(r##"Resets all player progress on all events for the currently authenticated player. This method is only accessible to whitelisted tester accounts for your application. All quests for this player will also be reset."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/events_reset-all", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("reset-all-for-all-players", + Some(r##"Resets all draft events for all players. This method is only available to user accounts for your developer console. All quests that use any of these events will also be reset."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/events_reset-all-for-all-players", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("reset-for-all-players", + Some(r##"Resets the event with the given ID for all players. This method is only available to user accounts for your developer console. Only draft events can be reset. All quests that use the event will also be reset."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/events_reset-for-all-players", + vec![ + (Some(r##"event-id"##), + None, + Some(r##"The ID of the event."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("reset-multiple-for-all-players", + Some(r##"Resets events with the given IDs for all players. This method is only available to user accounts for your developer console. Only draft events may be reset. All quests that use any of the events will also be reset."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/events_reset-multiple-for-all-players", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("players", "methods: 'hide' and 'unhide'", vec![ + ("hide", + Some(r##"Hide the given player's leaderboard scores from the given application. This method is only available to user accounts for your developer console."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/players_hide", + vec![ + (Some(r##"application-id"##), + None, + Some(r##"The application ID from the Google Play developer console."##), + Some(true), + Some(false)), + + (Some(r##"player-id"##), + None, + Some(r##"A player ID. A value of me may be used in place of the authenticated player's ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("unhide", + Some(r##"Unhide the given player's leaderboard scores from the given application. This method is only available to user accounts for your developer console."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/players_unhide", + vec![ + (Some(r##"application-id"##), + None, + Some(r##"The application ID from the Google Play developer console."##), + Some(true), + Some(false)), + + (Some(r##"player-id"##), + None, + Some(r##"A player ID. A value of me may be used in place of the authenticated player's ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("quests", "methods: 'reset', 'reset-all', 'reset-all-for-all-players', 'reset-for-all-players' and 'reset-multiple-for-all-players'", vec![ + ("reset", + Some(r##"Resets all player progress on the quest with the given ID for the currently authenticated player. This method is only accessible to whitelisted tester accounts for your application."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/quests_reset", + vec![ + (Some(r##"quest-id"##), + None, + Some(r##"The ID of the quest."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("reset-all", + Some(r##"Resets all player progress on all quests for the currently authenticated player. This method is only accessible to whitelisted tester accounts for your application."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/quests_reset-all", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("reset-all-for-all-players", + Some(r##"Resets all draft quests for all players. This method is only available to user accounts for your developer console."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/quests_reset-all-for-all-players", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("reset-for-all-players", + Some(r##"Resets all player progress on the quest with the given ID for all players. This method is only available to user accounts for your developer console. Only draft quests can be reset."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/quests_reset-for-all-players", + vec![ + (Some(r##"quest-id"##), + None, + Some(r##"The ID of the quest."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("reset-multiple-for-all-players", + Some(r##"Resets quests with the given IDs for all players. This method is only available to user accounts for your developer console. Only draft quests may be reset."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/quests_reset-multiple-for-all-players", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("rooms", "methods: 'reset' and 'reset-for-all-players'", vec![ + ("reset", + Some(r##"Reset all rooms for the currently authenticated player for your application. This method is only accessible to whitelisted tester accounts for your application."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/rooms_reset", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("reset-for-all-players", + Some(r##"Deletes rooms where the only room participants are from whitelisted tester accounts for your application. This method is only available to user accounts for your developer console."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/rooms_reset-for-all-players", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("scores", "methods: 'reset', 'reset-all', 'reset-all-for-all-players', 'reset-for-all-players' and 'reset-multiple-for-all-players'", vec![ + ("reset", + Some(r##"Resets scores for the leaderboard with the given ID for the currently authenticated player. This method is only accessible to whitelisted tester accounts for your application."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/scores_reset", + vec![ + (Some(r##"leaderboard-id"##), + None, + Some(r##"The ID of the leaderboard."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reset-all", + Some(r##"Resets all scores for all leaderboards for the currently authenticated players. This method is only accessible to whitelisted tester accounts for your application."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/scores_reset-all", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reset-all-for-all-players", + Some(r##"Resets scores for all draft leaderboards for all players. This method is only available to user accounts for your developer console."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/scores_reset-all-for-all-players", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("reset-for-all-players", + Some(r##"Resets scores for the leaderboard with the given ID for all players. This method is only available to user accounts for your developer console. Only draft leaderboards can be reset."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/scores_reset-for-all-players", + vec![ + (Some(r##"leaderboard-id"##), + None, + Some(r##"The ID of the leaderboard."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("reset-multiple-for-all-players", + Some(r##"Resets scores for the leaderboards with the given IDs for all players. This method is only available to user accounts for your developer console. Only draft leaderboards may be reset."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/scores_reset-multiple-for-all-players", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("turn-based-matches", "methods: 'reset' and 'reset-for-all-players'", vec![ + ("reset", + Some(r##"Reset all turn-based match data for a user. This method is only accessible to whitelisted tester accounts for your application."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/turn-based-matches_reset", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("reset-for-all-players", + Some(r##"Deletes turn-based matches where the only match participants are from whitelisted tester accounts for your application. This method is only available to user accounts for your developer console."##), + "Details at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli/turn-based-matches_reset-for-all-players", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ]; + + let mut app = App::new("gamesmanagement1-management") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150413") + .about("The Management API for Google Play Game Services.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_gamesmanagement1_management_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/gamesmanagement1_management/Cargo.toml b/gen/gamesmanagement1_management/Cargo.toml index 76eb65ff68..d40ab89cfe 100644 --- a/gen/gamesmanagement1_management/Cargo.toml +++ b/gen/gamesmanagement1_management/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-gamesmanagement1_management" -version = "0.1.6+20150413" +version = "0.1.7+20150413" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with Games Management (protocol v1management)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/gamesmanagement1_management" @@ -15,9 +15,10 @@ keywords = ["gamesManagement", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/gamesmanagement1_management/README.md b/gen/gamesmanagement1_management/README.md index e6c540334c..3af91f8946 100644 --- a/gen/gamesmanagement1_management/README.md +++ b/gen/gamesmanagement1_management/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-gamesmanagement1_management` library allows access to all features of the *Google Games Management* service. -This documentation was generated from *Games Management* crate version *0.1.6+20150413*, where *20150413* is the exact revision of the *gamesManagement:v1management* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *Games Management* crate version *0.1.7+20150413*, where *20150413* is the exact revision of the *gamesManagement:v1management* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *Games Management* *v1_management* API can be found at the [official documentation site](https://developers.google.com/games/services). @@ -172,7 +172,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_gamesmanagement1_management/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_gamesmanagement1_management/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/gamesmanagement1_management/src/cmn.rs b/gen/gamesmanagement1_management/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/gamesmanagement1_management/src/cmn.rs +++ b/gen/gamesmanagement1_management/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/gamesmanagement1_management/src/lib.rs b/gen/gamesmanagement1_management/src/lib.rs index f62eaf779c..e89050c14d 100644 --- a/gen/gamesmanagement1_management/src/lib.rs +++ b/gen/gamesmanagement1_management/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *Games Management* crate version *0.1.6+20150413*, where *20150413* is the exact revision of the *gamesManagement:v1management* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *Games Management* crate version *0.1.7+20150413*, where *20150413* is the exact revision of the *gamesManagement:v1management* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *Games Management* *v1_management* API can be found at the //! [official documentation site](https://developers.google.com/games/services). @@ -173,7 +173,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -182,7 +182,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -198,6 +197,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -318,7 +318,7 @@ impl<'a, C, A> GamesManagement<C, A> GamesManagement { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -348,7 +348,7 @@ impl<'a, C, A> GamesManagement<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1516,7 +1516,7 @@ impl<'a, C, A> AchievementResetAllForAllPlayerCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1538,7 +1538,7 @@ impl<'a, C, A> AchievementResetAllForAllPlayerCall<'a, C, A> where C: BorrowMut< access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1734,7 +1734,7 @@ impl<'a, C, A> AchievementResetForAllPlayerCall<'a, C, A> where C: BorrowMut<hyp if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1756,7 +1756,7 @@ impl<'a, C, A> AchievementResetForAllPlayerCall<'a, C, A> where C: BorrowMut<hyp access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1963,7 +1963,7 @@ impl<'a, C, A> AchievementResetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1985,7 +1985,7 @@ impl<'a, C, A> AchievementResetCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2153,6 +2153,7 @@ impl<'a, C, A> AchievementResetMultipleForAllPlayerCall<'a, C, A> where C: Borro /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2182,11 +2183,20 @@ impl<'a, C, A> AchievementResetMultipleForAllPlayerCall<'a, C, A> where C: Borro if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2209,7 +2219,7 @@ impl<'a, C, A> AchievementResetMultipleForAllPlayerCall<'a, C, A> where C: Borro request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2392,7 +2402,7 @@ impl<'a, C, A> AchievementResetAllCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2414,7 +2424,7 @@ impl<'a, C, A> AchievementResetAllCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2622,7 +2632,7 @@ impl<'a, C, A> PlayerHideCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2644,7 +2654,7 @@ impl<'a, C, A> PlayerHideCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2862,7 +2872,7 @@ impl<'a, C, A> PlayerUnhideCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2884,7 +2894,7 @@ impl<'a, C, A> PlayerUnhideCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3052,6 +3062,7 @@ impl<'a, C, A> ScoreResetMultipleForAllPlayerCall<'a, C, A> where C: BorrowMut<h /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3081,11 +3092,20 @@ impl<'a, C, A> ScoreResetMultipleForAllPlayerCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3108,7 +3128,7 @@ impl<'a, C, A> ScoreResetMultipleForAllPlayerCall<'a, C, A> where C: BorrowMut<h request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3290,7 +3310,7 @@ impl<'a, C, A> ScoreResetAllForAllPlayerCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3312,7 +3332,7 @@ impl<'a, C, A> ScoreResetAllForAllPlayerCall<'a, C, A> where C: BorrowMut<hyper: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3483,7 +3503,7 @@ impl<'a, C, A> ScoreResetAllCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3505,7 +3525,7 @@ impl<'a, C, A> ScoreResetAllCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3711,7 +3731,7 @@ impl<'a, C, A> ScoreResetForAllPlayerCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3733,7 +3753,7 @@ impl<'a, C, A> ScoreResetForAllPlayerCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3940,7 +3960,7 @@ impl<'a, C, A> ScoreResetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3962,7 +3982,7 @@ impl<'a, C, A> ScoreResetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4152,7 +4172,7 @@ impl<'a, C, A> TurnBasedMatcheResetCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4174,7 +4194,7 @@ impl<'a, C, A> TurnBasedMatcheResetCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4344,7 +4364,7 @@ impl<'a, C, A> TurnBasedMatcheResetForAllPlayerCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4366,7 +4386,7 @@ impl<'a, C, A> TurnBasedMatcheResetForAllPlayerCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4573,7 +4593,7 @@ impl<'a, C, A> ApplicationListHiddenCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4595,7 +4615,7 @@ impl<'a, C, A> ApplicationListHiddenCall<'a, C, A> where C: BorrowMut<hyper::Cli access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4799,7 +4819,7 @@ impl<'a, C, A> RoomResetForAllPlayerCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4821,7 +4841,7 @@ impl<'a, C, A> RoomResetForAllPlayerCall<'a, C, A> where C: BorrowMut<hyper::Cli access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4991,7 +5011,7 @@ impl<'a, C, A> RoomResetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5013,7 +5033,7 @@ impl<'a, C, A> RoomResetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5183,7 +5203,7 @@ impl<'a, C, A> QuestResetAllForAllPlayerCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5205,7 +5225,7 @@ impl<'a, C, A> QuestResetAllForAllPlayerCall<'a, C, A> where C: BorrowMut<hyper: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5353,6 +5373,7 @@ impl<'a, C, A> QuestResetMultipleForAllPlayerCall<'a, C, A> where C: BorrowMut<h /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5382,11 +5403,20 @@ impl<'a, C, A> QuestResetMultipleForAllPlayerCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5409,7 +5439,7 @@ impl<'a, C, A> QuestResetMultipleForAllPlayerCall<'a, C, A> where C: BorrowMut<h request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5591,7 +5621,7 @@ impl<'a, C, A> QuestResetAllCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5613,7 +5643,7 @@ impl<'a, C, A> QuestResetAllCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5809,7 +5839,7 @@ impl<'a, C, A> QuestResetForAllPlayerCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5831,7 +5861,7 @@ impl<'a, C, A> QuestResetForAllPlayerCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6037,7 +6067,7 @@ impl<'a, C, A> QuestResetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6059,7 +6089,7 @@ impl<'a, C, A> QuestResetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6239,7 +6269,7 @@ impl<'a, C, A> EventResetAllForAllPlayerCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6261,7 +6291,7 @@ impl<'a, C, A> EventResetAllForAllPlayerCall<'a, C, A> where C: BorrowMut<hyper: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6457,7 +6487,7 @@ impl<'a, C, A> EventResetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6479,7 +6509,7 @@ impl<'a, C, A> EventResetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6659,7 +6689,7 @@ impl<'a, C, A> EventResetAllCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6681,7 +6711,7 @@ impl<'a, C, A> EventResetAllCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6829,6 +6859,7 @@ impl<'a, C, A> EventResetMultipleForAllPlayerCall<'a, C, A> where C: BorrowMut<h /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6858,11 +6889,20 @@ impl<'a, C, A> EventResetMultipleForAllPlayerCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6885,7 +6925,7 @@ impl<'a, C, A> EventResetMultipleForAllPlayerCall<'a, C, A> where C: BorrowMut<h request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7093,7 +7133,7 @@ impl<'a, C, A> EventResetForAllPlayerCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7115,7 +7155,7 @@ impl<'a, C, A> EventResetForAllPlayerCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/gan1_beta1-cli/Cargo.toml b/gen/gan1_beta1-cli/Cargo.toml index 8bee2542ec..8544be5de6 100644 --- a/gen/gan1_beta1-cli/Cargo.toml +++ b/gen/gan1_beta1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-gan1_beta1-cli" -version = "0.1.0+20130205" +version = "0.2.0+20130205" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with gan (protocol v1beta1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/gan1_beta1-cli" @@ -17,15 +17,14 @@ keywords = ["gan", "google", "cli"] name = "gan1-beta1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-gan1_beta1] path = "../gan1_beta1" diff --git a/gen/gan1_beta1-cli/README.md b/gen/gan1_beta1-cli/README.md index af8cb6143e..987e262b36 100644 --- a/gen/gan1_beta1-cli/README.md +++ b/gen/gan1_beta1-cli/README.md @@ -10,26 +10,33 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *gan* API can be found at the +[official documentation site](https://developers.google.com/affiliate-network/). + # Usage -This documentation was generated from the *gan* API at revision *20130205*. The CLI is at version *0.1.0*. +This documentation was generated from the *gan* API at revision *20130205*. The CLI is at version *0.2.0*. ```bash - gan1-beta1 [options] advertisers get <role> <role-id> [-p <v>...] [-o <out>] - gan1-beta1 [options] advertisers list <role> <role-id> [-p <v>...] [-o <out>] - gan1-beta1 [options] cc-offers list <publisher> [-p <v>...] [-o <out>] - gan1-beta1 [options] events list <role> <role-id> [-p <v>...] [-o <out>] - gan1-beta1 [options] links get <role> <role-id> <link-id> [-p <v>...] [-o <out>] - gan1-beta1 [options] links insert <role> <role-id> -r <kv>... [-p <v>...] [-o <out>] - gan1-beta1 [options] links list <role> <role-id> [-p <v>...] [-o <out>] - gan1-beta1 [options] publishers get <role> <role-id> [-p <v>...] [-o <out>] - gan1-beta1 [options] publishers list <role> <role-id> [-p <v>...] [-o <out>] - gan1-beta1 [options] reports get <role> <role-id> <report-type> [-p <v>...] [-o <out>] +gan1-beta1 [options] + advertisers + get <role> <role-id> [-p <v>]... [-o <out>] + list <role> <role-id> [-p <v>]... [-o <out>] + cc-offers + list <publisher> [-p <v>]... [-o <out>] + events + list <role> <role-id> [-p <v>]... [-o <out>] + links + get <role> <role-id> <link-id> [-p <v>]... [-o <out>] + insert <role> <role-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <role> <role-id> [-p <v>]... [-o <out>] + publishers + get <role> <role-id> [-p <v>]... [-o <out>] + list <role> <role-id> [-p <v>]... [-o <out>] + reports + get <role> <role-id> <report-type> [-p <v>]... [-o <out>] gan1-beta1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_gan1_beta1_cli/index.html - Configuration: --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/gan1_beta1-cli/mkdocs.yml b/gen/gan1_beta1-cli/mkdocs.yml index b4b12fcef0..6519c38bc6 100644 --- a/gen/gan1_beta1-cli/mkdocs.yml +++ b/gen/gan1_beta1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: gan v0.1.0+20130205 +site_name: gan v0.2.0+20130205 site_url: http://byron.github.io/google-apis-rs/google-gan1_beta1-cli site_description: Write integrating applications with bcore diff --git a/gen/gan1_beta1-cli/src/cmn.rs b/gen/gan1_beta1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/gan1_beta1-cli/src/cmn.rs +++ b/gen/gan1_beta1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/gan1_beta1-cli/src/main.rs b/gen/gan1_beta1-cli/src/main.rs index 003733ffa4..44026c2e09 100644 --- a/gen/gan1_beta1-cli/src/main.rs +++ b/gen/gan1_beta1-cli/src/main.rs @@ -2,118 +2,103 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_gan1_beta1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - gan1-beta1 [options] advertisers get <role> <role-id> [-p <v>...] [-o <out>] - gan1-beta1 [options] advertisers list <role> <role-id> [-p <v>...] [-o <out>] - gan1-beta1 [options] cc-offers list <publisher> [-p <v>...] [-o <out>] - gan1-beta1 [options] events list <role> <role-id> [-p <v>...] [-o <out>] - gan1-beta1 [options] links get <role> <role-id> <link-id> [-p <v>...] [-o <out>] - gan1-beta1 [options] links insert <role> <role-id> -r <kv>... [-p <v>...] [-o <out>] - gan1-beta1 [options] links list <role> <role-id> [-p <v>...] [-o <out>] - gan1-beta1 [options] publishers get <role> <role-id> [-p <v>...] [-o <out>] - gan1-beta1 [options] publishers list <role> <role-id> [-p <v>...] [-o <out>] - gan1-beta1 [options] reports get <role> <role-id> <report-type> [-p <v>...] [-o <out>] - gan1-beta1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_gan1_beta1_cli/index.html - -Configuration: - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Gan<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _advertisers_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.advertisers().get(&self.opt.arg_role, &self.opt.arg_role_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _advertisers_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.advertisers().get(opt.value_of("role").unwrap_or(""), opt.value_of("role-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "advertiser-id" => { call = call.advertiser_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["advertiser-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _advertisers_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.advertisers().list(&self.opt.arg_role, &self.opt.arg_role_id); - for parg in self.opt.arg_v.iter() { + fn _advertisers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.advertisers().list(opt.value_of("role").unwrap_or(""), opt.value_of("role-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "relationship-status" => { @@ -137,47 +122,51 @@ impl Engine { "advertiser-category" => { call = call.advertiser_category(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["relationship-status", "min-seven-day-epc", "advertiser-category", "max-results", "page-token", "min-ninety-day-epc", "min-payout-rank"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _cc_offers_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.cc_offers().list(&self.opt.arg_publisher); - for parg in self.opt.arg_v.iter() { + fn _cc_offers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.cc_offers().list(opt.value_of("publisher").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { @@ -186,47 +175,51 @@ impl Engine { "advertiser" => { call = call.add_advertiser(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["advertiser", "projection"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _events_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.events().list(&self.opt.arg_role, &self.opt.arg_role_id); - for parg in self.opt.arg_v.iter() { + fn _events_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.events().list(opt.value_of("role").unwrap_or(""), opt.value_of("role-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "type" => { @@ -277,92 +270,100 @@ impl Engine { "advertiser-id" => { call = call.advertiser_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["status", "sku", "modify-date-max", "type", "link-id", "event-date-min", "member-id", "product-category", "order-id", "page-token", "advertiser-id", "max-results", "charge-type", "modify-date-min", "event-date-max", "publisher-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _links_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.links().get(&self.opt.arg_role, &self.opt.arg_role_id, &self.opt.arg_link_id); - for parg in self.opt.arg_v.iter() { + fn _links_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.links().get(opt.value_of("role").unwrap_or(""), opt.value_of("role-id").unwrap_or(""), opt.value_of("link-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _links_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _links_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Link::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -557,55 +558,60 @@ impl Engine { request.destination_url = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["advertiser-id", "amount", "authorship", "availability", "click-tracking-url", "create-date", "currency-code", "description", "destination-url", "duration", "end-date", "epc-ninety-day-average", "epc-seven-day-average", "free-gift", "free-shipping", "free-shipping-min", "id", "image-alt-text", "impression-tracking-url", "is-active", "kind", "link-type", "name", "percent-off", "percent-off-min", "price-cut", "price-cut-min", "promotion-codes", "promotion-type", "special-offers", "start-date"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.links().insert(request, &self.opt.arg_role, &self.opt.arg_role_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.links().insert(request, opt.value_of("role").unwrap_or(""), opt.value_of("role-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _links_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.links().list(&self.opt.arg_role, &self.opt.arg_role_id); - for parg in self.opt.arg_v.iter() { + fn _links_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.links().list(opt.value_of("role").unwrap_or(""), opt.value_of("role-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-date-min" => { @@ -647,93 +653,101 @@ impl Engine { "advertiser-id" => { call = call.add_advertiser_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-date-min", "link-type", "relationship-status", "search-text", "create-date-max", "create-date-min", "asset-size", "start-date-max", "advertiser-id", "page-token", "max-results", "promotion-type", "authorship"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _publishers_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.publishers().get(&self.opt.arg_role, &self.opt.arg_role_id); - for parg in self.opt.arg_v.iter() { + fn _publishers_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.publishers().get(opt.value_of("role").unwrap_or(""), opt.value_of("role-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "publisher-id" => { call = call.publisher_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["publisher-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _publishers_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.publishers().list(&self.opt.arg_role, &self.opt.arg_role_id); - for parg in self.opt.arg_v.iter() { + fn _publishers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.publishers().list(opt.value_of("role").unwrap_or(""), opt.value_of("role-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "relationship-status" => { @@ -757,47 +771,51 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["publisher-category", "relationship-status", "min-seven-day-epc", "min-ninety-day-epc", "page-token", "max-results", "min-payout-rank"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _reports_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.reports().get(&self.opt.arg_role, &self.opt.arg_role_id, &self.opt.arg_report_type); - for parg in self.opt.arg_v.iter() { + fn _reports_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.reports().get(opt.value_of("role").unwrap_or(""), opt.value_of("role-id").unwrap_or(""), opt.value_of("report-type").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "status" => { @@ -833,113 +851,150 @@ impl Engine { "advertiser-id" => { call = call.add_advertiser_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["status", "start-date", "end-date", "advertiser-id", "link-id", "max-results", "order-id", "start-index", "event-type", "calculate-totals", "publisher-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_advertisers { - if self.opt.cmd_get { - call_result = self._advertisers_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._advertisers_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("advertisers", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._advertisers_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._advertisers_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("advertisers".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("cc-offers", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._cc_offers_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("cc-offers".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("events", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._events_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("events".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("links", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._links_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._links_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._links_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("links".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("publishers", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._publishers_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._publishers_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("publishers".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("reports", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._reports_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("reports".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_cc_offers { - if self.opt.cmd_list { - call_result = self._cc_offers_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_events { - if self.opt.cmd_list { - call_result = self._events_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_links { - if self.opt.cmd_get { - call_result = self._links_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._links_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._links_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_publishers { - if self.opt.cmd_get { - call_result = self._publishers_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._publishers_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_reports { - if self.opt.cmd_get { - call_result = self._reports_get(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -952,7 +1007,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -965,7 +1020,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -975,37 +1030,428 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Gan::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("advertisers", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Retrieves data about a single advertiser if that the requesting advertiser/publisher has access to it. Only publishers can lookup advertisers. Advertisers can request information about themselves by omitting the advertiserId query parameter."##), + "Details at http://byron.github.io/google-apis-rs/google_gan1_beta1_cli/advertisers_get", + vec![ + (Some(r##"role"##), + None, + Some(r##"The role of the requester. Valid values: 'advertisers' or 'publishers'."##), + Some(true), + Some(false)), + + (Some(r##"role-id"##), + None, + Some(r##"The ID of the requesting advertiser or publisher."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves data about all advertisers that the requesting advertiser/publisher has access to."##), + "Details at http://byron.github.io/google-apis-rs/google_gan1_beta1_cli/advertisers_list", + vec![ + (Some(r##"role"##), + None, + Some(r##"The role of the requester. Valid values: 'advertisers' or 'publishers'."##), + Some(true), + Some(false)), + + (Some(r##"role-id"##), + None, + Some(r##"The ID of the requesting advertiser or publisher."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("cc-offers", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves credit card offers for the given publisher."##), + "Details at http://byron.github.io/google-apis-rs/google_gan1_beta1_cli/cc-offers_list", + vec![ + (Some(r##"publisher"##), + None, + Some(r##"The ID of the publisher in question."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("events", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves event data for a given advertiser/publisher."##), + "Details at http://byron.github.io/google-apis-rs/google_gan1_beta1_cli/events_list", + vec![ + (Some(r##"role"##), + None, + Some(r##"The role of the requester. Valid values: 'advertisers' or 'publishers'."##), + Some(true), + Some(false)), + + (Some(r##"role-id"##), + None, + Some(r##"The ID of the requesting advertiser or publisher."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("links", "methods: 'get', 'insert' and 'list'", vec![ + ("get", + Some(r##"Retrieves data about a single link if the requesting advertiser/publisher has access to it. Advertisers can look up their own links. Publishers can look up visible links or links belonging to advertisers they are in a relationship with."##), + "Details at http://byron.github.io/google-apis-rs/google_gan1_beta1_cli/links_get", + vec![ + (Some(r##"role"##), + None, + Some(r##"The role of the requester. Valid values: 'advertisers' or 'publishers'."##), + Some(true), + Some(false)), + + (Some(r##"role-id"##), + None, + Some(r##"The ID of the requesting advertiser or publisher."##), + Some(true), + Some(false)), + + (Some(r##"link-id"##), + None, + Some(r##"The ID of the link to look up."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new link."##), + "Details at http://byron.github.io/google-apis-rs/google_gan1_beta1_cli/links_insert", + vec![ + (Some(r##"role"##), + None, + Some(r##"The role of the requester. Valid values: 'advertisers' or 'publishers'."##), + Some(true), + Some(false)), + + (Some(r##"role-id"##), + None, + Some(r##"The ID of the requesting advertiser or publisher."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves all links that match the query parameters."##), + "Details at http://byron.github.io/google-apis-rs/google_gan1_beta1_cli/links_list", + vec![ + (Some(r##"role"##), + None, + Some(r##"The role of the requester. Valid values: 'advertisers' or 'publishers'."##), + Some(true), + Some(false)), + + (Some(r##"role-id"##), + None, + Some(r##"The ID of the requesting advertiser or publisher."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("publishers", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Retrieves data about a single advertiser if that the requesting advertiser/publisher has access to it. Only advertisers can look up publishers. Publishers can request information about themselves by omitting the publisherId query parameter."##), + "Details at http://byron.github.io/google-apis-rs/google_gan1_beta1_cli/publishers_get", + vec![ + (Some(r##"role"##), + None, + Some(r##"The role of the requester. Valid values: 'advertisers' or 'publishers'."##), + Some(true), + Some(false)), + + (Some(r##"role-id"##), + None, + Some(r##"The ID of the requesting advertiser or publisher."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves data about all publishers that the requesting advertiser/publisher has access to."##), + "Details at http://byron.github.io/google-apis-rs/google_gan1_beta1_cli/publishers_list", + vec![ + (Some(r##"role"##), + None, + Some(r##"The role of the requester. Valid values: 'advertisers' or 'publishers'."##), + Some(true), + Some(false)), + + (Some(r##"role-id"##), + None, + Some(r##"The ID of the requesting advertiser or publisher."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("reports", "methods: 'get'", vec![ + ("get", + Some(r##"Retrieves a report of the specified type."##), + "Details at http://byron.github.io/google-apis-rs/google_gan1_beta1_cli/reports_get", + vec![ + (Some(r##"role"##), + None, + Some(r##"The role of the requester. Valid values: 'advertisers' or 'publishers'."##), + Some(true), + Some(false)), + + (Some(r##"role-id"##), + None, + Some(r##"The ID of the requesting advertiser or publisher."##), + Some(true), + Some(false)), + + (Some(r##"report-type"##), + None, + Some(r##"The type of report being requested. Valid values: 'order_delta'. Required."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("gan1-beta1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20130205") + .about("Lets you have programmatic access to your Google Affiliate Network data.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_gan1_beta1_cli") + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/gan1_beta1/Cargo.toml b/gen/gan1_beta1/Cargo.toml index 34ca099c6e..4110b86760 100644 --- a/gen/gan1_beta1/Cargo.toml +++ b/gen/gan1_beta1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-gan1_beta1" -version = "0.1.6+20130205" +version = "0.1.7+20130205" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with gan (protocol v1beta1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/gan1_beta1" @@ -15,9 +15,10 @@ keywords = ["gan", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/gan1_beta1/README.md b/gen/gan1_beta1/README.md index fc6bb8792c..cac2b31079 100644 --- a/gen/gan1_beta1/README.md +++ b/gen/gan1_beta1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-gan1_beta1` library allows access to all features of the *Google gan* service. -This documentation was generated from *gan* crate version *0.1.6+20130205*, where *20130205* is the exact revision of the *gan:v1beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *gan* crate version *0.1.7+20130205*, where *20130205* is the exact revision of the *gan:v1beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *gan* *v1_beta1* API can be found at the [official documentation site](https://developers.google.com/affiliate-network/). @@ -182,7 +182,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_gan1_beta1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_gan1_beta1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/gan1_beta1/src/cmn.rs b/gen/gan1_beta1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/gan1_beta1/src/cmn.rs +++ b/gen/gan1_beta1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/gan1_beta1/src/lib.rs b/gen/gan1_beta1/src/lib.rs index 127b5dda82..40bf5065c0 100644 --- a/gen/gan1_beta1/src/lib.rs +++ b/gen/gan1_beta1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *gan* crate version *0.1.6+20130205*, where *20130205* is the exact revision of the *gan:v1beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *gan* crate version *0.1.7+20130205*, where *20130205* is the exact revision of the *gan:v1beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *gan* *v1_beta1* API can be found at the //! [official documentation site](https://developers.google.com/affiliate-network/). @@ -183,7 +183,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -192,7 +192,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -208,6 +207,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -315,7 +315,7 @@ impl<'a, C, A> Gan<C, A> Gan { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -339,7 +339,7 @@ impl<'a, C, A> Gan<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1760,7 +1760,7 @@ impl<'a, C, A> PublisherListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1768,7 +1768,7 @@ impl<'a, C, A> PublisherListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -2042,7 +2042,7 @@ impl<'a, C, A> PublisherGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2050,7 +2050,7 @@ impl<'a, C, A> PublisherGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -2219,6 +2219,7 @@ impl<'a, C, A> LinkInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Link)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2284,11 +2285,20 @@ impl<'a, C, A> LinkInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2297,7 +2307,7 @@ impl<'a, C, A> LinkInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -2531,7 +2541,7 @@ impl<'a, C, A> LinkGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2539,7 +2549,7 @@ impl<'a, C, A> LinkGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -2846,7 +2856,7 @@ impl<'a, C, A> LinkListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2854,7 +2864,7 @@ impl<'a, C, A> LinkListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -3241,7 +3251,7 @@ impl<'a, C, A> ReportGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3249,7 +3259,7 @@ impl<'a, C, A> ReportGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -3572,7 +3582,7 @@ impl<'a, C, A> CcOfferListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3580,7 +3590,7 @@ impl<'a, C, A> CcOfferListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -3810,7 +3820,7 @@ impl<'a, C, A> AdvertiserGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3818,7 +3828,7 @@ impl<'a, C, A> AdvertiserGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -4080,7 +4090,7 @@ impl<'a, C, A> AdvertiserListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4088,7 +4098,7 @@ impl<'a, C, A> AdvertiserListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -4437,7 +4447,7 @@ impl<'a, C, A> EventListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4445,7 +4455,7 @@ impl<'a, C, A> EventListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); diff --git a/gen/genomics1_beta2-cli/Cargo.toml b/gen/genomics1_beta2-cli/Cargo.toml index a8f96eea04..63b88a9f59 100644 --- a/gen/genomics1_beta2-cli/Cargo.toml +++ b/gen/genomics1_beta2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-genomics1_beta2-cli" -version = "0.1.0+20150326" +version = "0.2.0+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with genomics (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/genomics1_beta2-cli" @@ -17,15 +17,14 @@ keywords = ["genomics", "google", "cli"] name = "genomics1-beta2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-genomics1_beta2] path = "../genomics1_beta2" diff --git a/gen/genomics1_beta2-cli/README.md b/gen/genomics1_beta2-cli/README.md index 94b1a1e389..68e3639ed2 100644 --- a/gen/genomics1_beta2-cli/README.md +++ b/gen/genomics1_beta2-cli/README.md @@ -10,80 +10,94 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *genomics* API can be found at the +[official documentation site](https://developers.google.com/genomics/v1beta2/reference). + # Usage -This documentation was generated from the *genomics* API at revision *20150326*. The CLI is at version *0.1.0*. +This documentation was generated from the *genomics* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - genomics1-beta2 [options] annotation-sets create -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotation-sets delete <annotation-set-id> [-p <v>...] - genomics1-beta2 [options] annotation-sets get <annotation-set-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotation-sets patch <annotation-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotation-sets search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotation-sets update <annotation-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotations batch-create -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotations create -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotations delete <annotation-id> [-p <v>...] - genomics1-beta2 [options] annotations get <annotation-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotations patch <annotation-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotations search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotations update <annotation-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] callsets create -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] callsets delete <call-set-id> [-p <v>...] - genomics1-beta2 [options] callsets get <call-set-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] callsets patch <call-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] callsets search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] callsets update <call-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] datasets create -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] datasets delete <dataset-id> [-p <v>...] - genomics1-beta2 [options] datasets get <dataset-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] datasets list [-p <v>...] [-o <out>] - genomics1-beta2 [options] datasets patch <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] datasets undelete <dataset-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] datasets update <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] experimental jobs-create -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] jobs cancel <job-id> [-p <v>...] - genomics1-beta2 [options] jobs get <job-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] jobs search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets align -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets call -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets coveragebuckets-list <read-group-set-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets delete <read-group-set-id> [-p <v>...] - genomics1-beta2 [options] readgroupsets export -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets get <read-group-set-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets import -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets patch <read-group-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets update <read-group-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] reads search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] references bases-list <reference-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] references get <reference-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] references search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] referencesets get <reference-set-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] referencesets search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] streaming-readstore streamreads -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variants create -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variants delete <variant-id> [-p <v>...] - genomics1-beta2 [options] variants get <variant-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] variants search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variants update <variant-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variantsets delete <variant-set-id> [-p <v>...] - genomics1-beta2 [options] variantsets export <variant-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variantsets get <variant-set-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] variantsets import-variants <variant-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variantsets merge-variants <variant-set-id> -r <kv>... [-p <v>...] - genomics1-beta2 [options] variantsets patch <variant-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variantsets search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variantsets update <variant-set-id> -r <kv>... [-p <v>...] [-o <out>] +genomics1-beta2 [options] + annotation-sets + create (-r <kv>)... [-p <v>]... [-o <out>] + delete <annotation-set-id> [-p <v>]... + get <annotation-set-id> [-p <v>]... [-o <out>] + patch <annotation-set-id> (-r <kv>)... [-p <v>]... [-o <out>] + search (-r <kv>)... [-p <v>]... [-o <out>] + update <annotation-set-id> (-r <kv>)... [-p <v>]... [-o <out>] + annotations + batch-create (-r <kv>)... [-p <v>]... [-o <out>] + create (-r <kv>)... [-p <v>]... [-o <out>] + delete <annotation-id> [-p <v>]... + get <annotation-id> [-p <v>]... [-o <out>] + patch <annotation-id> (-r <kv>)... [-p <v>]... [-o <out>] + search (-r <kv>)... [-p <v>]... [-o <out>] + update <annotation-id> (-r <kv>)... [-p <v>]... [-o <out>] + callsets + create (-r <kv>)... [-p <v>]... [-o <out>] + delete <call-set-id> [-p <v>]... + get <call-set-id> [-p <v>]... [-o <out>] + patch <call-set-id> (-r <kv>)... [-p <v>]... [-o <out>] + search (-r <kv>)... [-p <v>]... [-o <out>] + update <call-set-id> (-r <kv>)... [-p <v>]... [-o <out>] + datasets + create (-r <kv>)... [-p <v>]... [-o <out>] + delete <dataset-id> [-p <v>]... + get <dataset-id> [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + patch <dataset-id> (-r <kv>)... [-p <v>]... [-o <out>] + undelete <dataset-id> [-p <v>]... [-o <out>] + update <dataset-id> (-r <kv>)... [-p <v>]... [-o <out>] + experimental + jobs-create (-r <kv>)... [-p <v>]... [-o <out>] + jobs + cancel <job-id> [-p <v>]... + get <job-id> [-p <v>]... [-o <out>] + search (-r <kv>)... [-p <v>]... [-o <out>] + readgroupsets + align (-r <kv>)... [-p <v>]... [-o <out>] + call (-r <kv>)... [-p <v>]... [-o <out>] + coveragebuckets-list <read-group-set-id> [-p <v>]... [-o <out>] + delete <read-group-set-id> [-p <v>]... + export (-r <kv>)... [-p <v>]... [-o <out>] + get <read-group-set-id> [-p <v>]... [-o <out>] + import (-r <kv>)... [-p <v>]... [-o <out>] + patch <read-group-set-id> (-r <kv>)... [-p <v>]... [-o <out>] + search (-r <kv>)... [-p <v>]... [-o <out>] + update <read-group-set-id> (-r <kv>)... [-p <v>]... [-o <out>] + reads + search (-r <kv>)... [-p <v>]... [-o <out>] + references + bases-list <reference-id> [-p <v>]... [-o <out>] + get <reference-id> [-p <v>]... [-o <out>] + search (-r <kv>)... [-p <v>]... [-o <out>] + referencesets + get <reference-set-id> [-p <v>]... [-o <out>] + search (-r <kv>)... [-p <v>]... [-o <out>] + streaming-readstore + streamreads (-r <kv>)... [-p <v>]... [-o <out>] + variants + create (-r <kv>)... [-p <v>]... [-o <out>] + delete <variant-id> [-p <v>]... + get <variant-id> [-p <v>]... [-o <out>] + search (-r <kv>)... [-p <v>]... [-o <out>] + update <variant-id> (-r <kv>)... [-p <v>]... [-o <out>] + variantsets + delete <variant-set-id> [-p <v>]... + export <variant-set-id> (-r <kv>)... [-p <v>]... [-o <out>] + get <variant-set-id> [-p <v>]... [-o <out>] + import-variants <variant-set-id> (-r <kv>)... [-p <v>]... [-o <out>] + merge-variants <variant-set-id> (-r <kv>)... [-p <v>]... + patch <variant-set-id> (-r <kv>)... [-p <v>]... [-o <out>] + search (-r <kv>)... [-p <v>]... [-o <out>] + update <variant-set-id> (-r <kv>)... [-p <v>]... [-o <out>] genomics1-beta2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/genomics1_beta2-cli/mkdocs.yml b/gen/genomics1_beta2-cli/mkdocs.yml index 45585ed65c..ce20583963 100644 --- a/gen/genomics1_beta2-cli/mkdocs.yml +++ b/gen/genomics1_beta2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: genomics v0.1.0+20150326 +site_name: genomics v0.2.0+20150326 site_url: http://byron.github.io/google-apis-rs/google-genomics1_beta2-cli site_description: Write integrating applications with bcore diff --git a/gen/genomics1_beta2-cli/src/cmn.rs b/gen/genomics1_beta2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/genomics1_beta2-cli/src/cmn.rs +++ b/gen/genomics1_beta2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/genomics1_beta2-cli/src/main.rs b/gen/genomics1_beta2-cli/src/main.rs index db0cce2dc6..52a418425b 100644 --- a/gen/genomics1_beta2-cli/src/main.rs +++ b/gen/genomics1_beta2-cli/src/main.rs @@ -2,128 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_genomics1_beta2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - genomics1-beta2 [options] annotation-sets create -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotation-sets delete <annotation-set-id> [-p <v>...] - genomics1-beta2 [options] annotation-sets get <annotation-set-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotation-sets patch <annotation-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotation-sets search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotation-sets update <annotation-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotations batch-create -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotations create -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotations delete <annotation-id> [-p <v>...] - genomics1-beta2 [options] annotations get <annotation-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotations patch <annotation-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotations search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] annotations update <annotation-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] callsets create -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] callsets delete <call-set-id> [-p <v>...] - genomics1-beta2 [options] callsets get <call-set-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] callsets patch <call-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] callsets search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] callsets update <call-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] datasets create -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] datasets delete <dataset-id> [-p <v>...] - genomics1-beta2 [options] datasets get <dataset-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] datasets list [-p <v>...] [-o <out>] - genomics1-beta2 [options] datasets patch <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] datasets undelete <dataset-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] datasets update <dataset-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] experimental jobs-create -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] jobs cancel <job-id> [-p <v>...] - genomics1-beta2 [options] jobs get <job-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] jobs search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets align -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets call -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets coveragebuckets-list <read-group-set-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets delete <read-group-set-id> [-p <v>...] - genomics1-beta2 [options] readgroupsets export -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets get <read-group-set-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets import -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets patch <read-group-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] readgroupsets update <read-group-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] reads search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] references bases-list <reference-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] references get <reference-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] references search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] referencesets get <reference-set-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] referencesets search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] streaming-readstore streamreads -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variants create -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variants delete <variant-id> [-p <v>...] - genomics1-beta2 [options] variants get <variant-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] variants search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variants update <variant-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variantsets delete <variant-set-id> [-p <v>...] - genomics1-beta2 [options] variantsets export <variant-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variantsets get <variant-set-id> [-p <v>...] [-o <out>] - genomics1-beta2 [options] variantsets import-variants <variant-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variantsets merge-variants <variant-set-id> -r <kv>... [-p <v>...] - genomics1-beta2 [options] variantsets patch <variant-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variantsets search -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 [options] variantsets update <variant-set-id> -r <kv>... [-p <v>...] [-o <out>] - genomics1-beta2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Genomics<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _annotation_sets_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _annotation_sets_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AnnotationSet::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -157,150 +84,158 @@ impl Engine { request.dataset_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["dataset-id", "id", "name", "reference-set-id", "source-uri", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.annotation_sets().create(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _annotation_sets_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.annotation_sets().delete(&self.opt.arg_annotation_set_id); - for parg in self.opt.arg_v.iter() { + fn _annotation_sets_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.annotation_sets().delete(opt.value_of("annotation-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _annotation_sets_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.annotation_sets().get(&self.opt.arg_annotation_set_id); - for parg in self.opt.arg_v.iter() { + fn _annotation_sets_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.annotation_sets().get(opt.value_of("annotation-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _annotation_sets_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _annotation_sets_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AnnotationSet::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -334,60 +269,65 @@ impl Engine { request.dataset_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["dataset-id", "id", "name", "reference-set-id", "source-uri", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.annotation_sets().patch(request, &self.opt.arg_annotation_set_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.annotation_sets().patch(request, opt.value_of("annotation-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _annotation_sets_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _annotation_sets_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SearchAnnotationSetsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -427,60 +367,65 @@ impl Engine { request.types.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["dataset-ids", "name", "page-size", "page-token", "reference-set-id", "types"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.annotation_sets().search(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _annotation_sets_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _annotation_sets_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AnnotationSet::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -514,60 +459,65 @@ impl Engine { request.dataset_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["dataset-id", "id", "name", "reference-set-id", "source-uri", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.annotation_sets().update(request, &self.opt.arg_annotation_set_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.annotation_sets().update(request, opt.value_of("annotation-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _annotations_batch_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _annotations_batch_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::BatchCreateAnnotationsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -583,60 +533,65 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.annotations().batch_create(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _annotations_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _annotations_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Annotation::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -751,150 +706,158 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["alternate-bases", "annotation-set-id", "clinical-significance", "coding-sequence", "effect", "end", "gene-id", "id", "name", "position", "reference-id", "reference-name", "reverse-strand", "start", "transcript", "transcript-ids", "type", "variant"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.annotations().create(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _annotations_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.annotations().delete(&self.opt.arg_annotation_id); - for parg in self.opt.arg_v.iter() { + fn _annotations_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.annotations().delete(opt.value_of("annotation-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _annotations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.annotations().get(&self.opt.arg_annotation_id); - for parg in self.opt.arg_v.iter() { + fn _annotations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.annotations().get(opt.value_of("annotation-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _annotations_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _annotations_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Annotation::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1009,60 +972,65 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["alternate-bases", "annotation-set-id", "clinical-significance", "coding-sequence", "effect", "end", "gene-id", "id", "name", "position", "reference-id", "reference-name", "reverse-strand", "start", "transcript", "transcript-ids", "type", "variant"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.annotations().patch(request, &self.opt.arg_annotation_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.annotations().patch(request, opt.value_of("annotation-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _annotations_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _annotations_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SearchAnnotationsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1114,60 +1082,65 @@ impl Engine { request.page_size = Some(arg_from_str(value.unwrap_or("-0"), err, "page-size", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["annotation-set-ids", "end", "page-size", "page-token", "range", "reference-id", "reference-name", "start"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.annotations().search(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _annotations_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _annotations_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Annotation::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1282,60 +1255,65 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["alternate-bases", "annotation-set-id", "clinical-significance", "coding-sequence", "effect", "end", "gene-id", "id", "name", "position", "reference-id", "reference-name", "reverse-strand", "start", "transcript", "transcript-ids", "type", "variant"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.annotations().update(request, &self.opt.arg_annotation_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.annotations().update(request, opt.value_of("annotation-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _callsets_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _callsets_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CallSet::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1369,150 +1347,158 @@ impl Engine { request.created = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["created", "id", "name", "sample-id", "variant-set-ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.callsets().create(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _callsets_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.callsets().delete(&self.opt.arg_call_set_id); - for parg in self.opt.arg_v.iter() { + fn _callsets_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.callsets().delete(opt.value_of("call-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _callsets_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.callsets().get(&self.opt.arg_call_set_id); - for parg in self.opt.arg_v.iter() { + fn _callsets_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.callsets().get(opt.value_of("call-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _callsets_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _callsets_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CallSet::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1546,60 +1532,65 @@ impl Engine { request.created = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["created", "id", "name", "sample-id", "variant-set-ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.callsets().patch(request, &self.opt.arg_call_set_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.callsets().patch(request, opt.value_of("call-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _callsets_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _callsets_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SearchCallSetsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1630,60 +1621,65 @@ impl Engine { request.page_size = Some(arg_from_str(value.unwrap_or("-0"), err, "page-size", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["name", "page-size", "page-token", "variant-set-ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.callsets().search(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _callsets_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _callsets_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CallSet::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1717,60 +1713,65 @@ impl Engine { request.created = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["created", "id", "name", "sample-id", "variant-set-ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.callsets().update(request, &self.opt.arg_call_set_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.callsets().update(request, opt.value_of("call-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _datasets_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Dataset::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1798,148 +1799,156 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "is-public", "name", "project-number"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.datasets().create(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.datasets().delete(&self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + fn _datasets_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.datasets().delete(opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _datasets_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.datasets().get(&self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + fn _datasets_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.datasets().get(opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _datasets_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.datasets().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "project-number" => { @@ -1951,52 +1960,56 @@ impl Engine { "page-size" => { call = call.page_size(arg_from_str(value.unwrap_or("-0"), err, "page-size", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "project-number", "page-size"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _datasets_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Dataset::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2024,106 +2037,115 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "is-public", "name", "project-number"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.datasets().patch(request, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.datasets().patch(request, opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_undelete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.datasets().undelete(&self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + fn _datasets_undelete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.datasets().undelete(opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _datasets_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _datasets_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Dataset::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2151,60 +2173,65 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "is-public", "name", "project-number"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.datasets().update(request, &self.opt.arg_dataset_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.datasets().update(request, opt.value_of("dataset-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _experimental_jobs_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _experimental_jobs_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ExperimentalCreateJobRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2244,150 +2271,158 @@ impl Engine { request.project_number = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["align", "call-variants", "gcs-output-path", "paired-source-uris", "project-number", "source-uris"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.experimental().jobs_create(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _jobs_cancel(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.jobs().cancel(&self.opt.arg_job_id); - for parg in self.opt.arg_v.iter() { + fn _jobs_cancel(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.jobs().cancel(opt.value_of("job-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _jobs_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.jobs().get(&self.opt.arg_job_id); - for parg in self.opt.arg_v.iter() { + fn _jobs_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.jobs().get(opt.value_of("job-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _jobs_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _jobs_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SearchJobsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2424,60 +2459,65 @@ impl Engine { request.project_number = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["created-after", "created-before", "page-size", "page-token", "project-number", "status"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.jobs().search(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _readgroupsets_align(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _readgroupsets_align(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AlignReadGroupSetsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2595,60 +2635,65 @@ impl Engine { request.dataset_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bam-source-uris", "dataset-id", "first-source-uris", "interleaved-fastq-source", "library-name", "metadata", "paired-fastq-source", "platform-name", "platform-unit", "read-group-name", "read-group-set-id", "sample-name", "second-source-uris", "source-uris"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.readgroupsets().align(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _readgroupsets_call(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _readgroupsets_call(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CallReadGroupSetsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2676,58 +2721,63 @@ impl Engine { request.dataset_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["dataset-id", "read-group-set-id", "source-uris"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.readgroupsets().call(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _readgroupsets_coveragebuckets_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.readgroupsets().coveragebuckets_list(&self.opt.arg_read_group_set_id); - for parg in self.opt.arg_v.iter() { + fn _readgroupsets_coveragebuckets_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.readgroupsets().coveragebuckets_list(opt.value_of("read-group-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "target-bucket-width" => { @@ -2748,96 +2798,99 @@ impl Engine { "page-size" => { call = call.page_size(arg_from_str(value.unwrap_or("-0"), err, "page-size", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-size", "range-start", "range-end", "range-reference-name", "page-token", "target-bucket-width"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _readgroupsets_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.readgroupsets().delete(&self.opt.arg_read_group_set_id); - for parg in self.opt.arg_v.iter() { + fn _readgroupsets_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.readgroupsets().delete(opt.value_of("read-group-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _readgroupsets_export(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _readgroupsets_export(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ExportReadGroupSetsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2871,106 +2924,115 @@ impl Engine { request.project_number = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["export-uri", "project-number", "read-group-set-ids", "reference-names"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.readgroupsets().export(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _readgroupsets_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.readgroupsets().get(&self.opt.arg_read_group_set_id); - for parg in self.opt.arg_v.iter() { + fn _readgroupsets_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.readgroupsets().get(opt.value_of("read-group-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _readgroupsets_import(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _readgroupsets_import(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ImportReadGroupSetsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3001,60 +3063,65 @@ impl Engine { request.dataset_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["dataset-id", "partition-strategy", "reference-set-id", "source-uris"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.readgroupsets().import(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _readgroupsets_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _readgroupsets_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ReadGroupSet::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3085,60 +3152,65 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["dataset-id", "filename", "id", "name", "reference-set-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.readgroupsets().patch(request, &self.opt.arg_read_group_set_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.readgroupsets().patch(request, opt.value_of("read-group-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _readgroupsets_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _readgroupsets_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SearchReadGroupSetsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3169,60 +3241,65 @@ impl Engine { request.page_size = Some(arg_from_str(value.unwrap_or("-0"), err, "page-size", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["dataset-ids", "name", "page-size", "page-token"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.readgroupsets().search(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _readgroupsets_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _readgroupsets_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ReadGroupSet::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3253,60 +3330,65 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["dataset-id", "filename", "id", "name", "reference-set-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.readgroupsets().update(request, &self.opt.arg_read_group_set_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.readgroupsets().update(request, opt.value_of("read-group-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _reads_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _reads_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SearchReadsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3349,58 +3431,63 @@ impl Engine { request.end = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["end", "page-size", "page-token", "read-group-ids", "read-group-set-ids", "reference-name", "start"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.reads().search(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _references_bases_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.references().bases_list(&self.opt.arg_reference_id); - for parg in self.opt.arg_v.iter() { + fn _references_bases_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.references().bases_list(opt.value_of("reference-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start" => { @@ -3415,98 +3502,106 @@ impl Engine { "end" => { call = call.end(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start", "end", "page-size", "page-token"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _references_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.references().get(&self.opt.arg_reference_id); - for parg in self.opt.arg_v.iter() { + fn _references_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.references().get(opt.value_of("reference-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _references_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _references_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SearchReferencesRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3543,106 +3638,115 @@ impl Engine { request.page_size = Some(arg_from_str(value.unwrap_or("-0"), err, "page-size", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["accessions", "md5checksums", "page-size", "page-token", "reference-set-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.references().search(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _referencesets_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.referencesets().get(&self.opt.arg_reference_set_id); - for parg in self.opt.arg_v.iter() { + fn _referencesets_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.referencesets().get(opt.value_of("reference-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _referencesets_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _referencesets_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SearchReferenceSetsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3679,60 +3783,65 @@ impl Engine { request.page_token = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["accessions", "assembly-id", "md5checksums", "page-size", "page-token"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.referencesets().search(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _streaming_readstore_streamreads(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _streaming_readstore_streamreads(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::StreamReadsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3763,57 +3872,62 @@ impl Engine { request.reference_name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["end", "read-group-set-ids", "reference-name", "start"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.streaming_readstore().streamreads(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _variants_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _variants_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Variant::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3871,150 +3985,158 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["alternate-bases", "created", "end", "filter", "id", "names", "quality", "reference-bases", "reference-name", "start", "variant-set-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.variants().create(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _variants_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.variants().delete(&self.opt.arg_variant_id); - for parg in self.opt.arg_v.iter() { + fn _variants_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.variants().delete(opt.value_of("variant-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _variants_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.variants().get(&self.opt.arg_variant_id); - for parg in self.opt.arg_v.iter() { + fn _variants_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.variants().get(opt.value_of("variant-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _variants_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _variants_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SearchVariantsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4063,60 +4185,65 @@ impl Engine { request.variant_set_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["call-set-ids", "end", "max-calls", "page-size", "page-token", "reference-name", "start", "variant-name", "variant-set-ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.variants().search(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _variants_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _variants_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Variant::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4174,104 +4301,108 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["alternate-bases", "created", "end", "filter", "id", "names", "quality", "reference-bases", "reference-name", "start", "variant-set-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.variants().update(request, &self.opt.arg_variant_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.variants().update(request, opt.value_of("variant-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _variantsets_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.variantsets().delete(&self.opt.arg_variant_set_id); - for parg in self.opt.arg_v.iter() { + fn _variantsets_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.variantsets().delete(opt.value_of("variant-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _variantsets_export(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _variantsets_export(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ExportVariantSetRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4305,106 +4436,115 @@ impl Engine { request.bigquery_table = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bigquery-dataset", "bigquery-table", "call-set-ids", "format", "project-number"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.variantsets().export(request, &self.opt.arg_variant_set_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.variantsets().export(request, opt.value_of("variant-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _variantsets_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.variantsets().get(&self.opt.arg_variant_set_id); - for parg in self.opt.arg_v.iter() { + fn _variantsets_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.variantsets().get(opt.value_of("variant-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _variantsets_import_variants(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _variantsets_import_variants(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ImportVariantsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4429,60 +4569,65 @@ impl Engine { request.format = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["format", "source-uris"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.variantsets().import_variants(request, &self.opt.arg_variant_set_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.variantsets().import_variants(request, opt.value_of("variant-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _variantsets_merge_variants(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _variantsets_merge_variants(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::MergeVariantsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4498,58 +4643,58 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.variantsets().merge_variants(request, &self.opt.arg_variant_set_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.variantsets().merge_variants(request, opt.value_of("variant-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _variantsets_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _variantsets_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::VariantSet::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4571,60 +4716,65 @@ impl Engine { request.dataset_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["dataset-id", "id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.variantsets().patch(request, &self.opt.arg_variant_set_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.variantsets().patch(request, opt.value_of("variant-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _variantsets_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _variantsets_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SearchVariantSetsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4652,60 +4802,65 @@ impl Engine { request.page_size = Some(arg_from_str(value.unwrap_or("-0"), err, "page-size", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["dataset-ids", "page-size", "page-token"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.variantsets().search(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _variantsets_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _variantsets_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::VariantSet::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4727,259 +4882,368 @@ impl Engine { request.dataset_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["dataset-id", "id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.variantsets().update(request, &self.opt.arg_variant_set_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.variantsets().update(request, opt.value_of("variant-set-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_annotation_sets { - if self.opt.cmd_create { - call_result = self._annotation_sets_create(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._annotation_sets_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._annotation_sets_get(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._annotation_sets_patch(dry_run, &mut err); - } else if self.opt.cmd_search { - call_result = self._annotation_sets_search(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._annotation_sets_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("annotation-sets", Some(opt)) => { + match opt.subcommand() { + ("create", Some(opt)) => { + call_result = self._annotation_sets_create(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._annotation_sets_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._annotation_sets_get(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._annotation_sets_patch(opt, dry_run, &mut err); + }, + ("search", Some(opt)) => { + call_result = self._annotation_sets_search(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._annotation_sets_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("annotation-sets".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("annotations", Some(opt)) => { + match opt.subcommand() { + ("batch-create", Some(opt)) => { + call_result = self._annotations_batch_create(opt, dry_run, &mut err); + }, + ("create", Some(opt)) => { + call_result = self._annotations_create(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._annotations_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._annotations_get(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._annotations_patch(opt, dry_run, &mut err); + }, + ("search", Some(opt)) => { + call_result = self._annotations_search(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._annotations_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("annotations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("callsets", Some(opt)) => { + match opt.subcommand() { + ("create", Some(opt)) => { + call_result = self._callsets_create(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._callsets_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._callsets_get(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._callsets_patch(opt, dry_run, &mut err); + }, + ("search", Some(opt)) => { + call_result = self._callsets_search(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._callsets_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("callsets".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("datasets", Some(opt)) => { + match opt.subcommand() { + ("create", Some(opt)) => { + call_result = self._datasets_create(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._datasets_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._datasets_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._datasets_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._datasets_patch(opt, dry_run, &mut err); + }, + ("undelete", Some(opt)) => { + call_result = self._datasets_undelete(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._datasets_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("datasets".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("experimental", Some(opt)) => { + match opt.subcommand() { + ("jobs-create", Some(opt)) => { + call_result = self._experimental_jobs_create(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("experimental".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("jobs", Some(opt)) => { + match opt.subcommand() { + ("cancel", Some(opt)) => { + call_result = self._jobs_cancel(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._jobs_get(opt, dry_run, &mut err); + }, + ("search", Some(opt)) => { + call_result = self._jobs_search(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("jobs".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("readgroupsets", Some(opt)) => { + match opt.subcommand() { + ("align", Some(opt)) => { + call_result = self._readgroupsets_align(opt, dry_run, &mut err); + }, + ("call", Some(opt)) => { + call_result = self._readgroupsets_call(opt, dry_run, &mut err); + }, + ("coveragebuckets-list", Some(opt)) => { + call_result = self._readgroupsets_coveragebuckets_list(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._readgroupsets_delete(opt, dry_run, &mut err); + }, + ("export", Some(opt)) => { + call_result = self._readgroupsets_export(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._readgroupsets_get(opt, dry_run, &mut err); + }, + ("import", Some(opt)) => { + call_result = self._readgroupsets_import(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._readgroupsets_patch(opt, dry_run, &mut err); + }, + ("search", Some(opt)) => { + call_result = self._readgroupsets_search(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._readgroupsets_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("readgroupsets".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("reads", Some(opt)) => { + match opt.subcommand() { + ("search", Some(opt)) => { + call_result = self._reads_search(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("reads".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("references", Some(opt)) => { + match opt.subcommand() { + ("bases-list", Some(opt)) => { + call_result = self._references_bases_list(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._references_get(opt, dry_run, &mut err); + }, + ("search", Some(opt)) => { + call_result = self._references_search(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("references".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("referencesets", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._referencesets_get(opt, dry_run, &mut err); + }, + ("search", Some(opt)) => { + call_result = self._referencesets_search(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("referencesets".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("streaming-readstore", Some(opt)) => { + match opt.subcommand() { + ("streamreads", Some(opt)) => { + call_result = self._streaming_readstore_streamreads(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("streaming-readstore".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("variants", Some(opt)) => { + match opt.subcommand() { + ("create", Some(opt)) => { + call_result = self._variants_create(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._variants_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._variants_get(opt, dry_run, &mut err); + }, + ("search", Some(opt)) => { + call_result = self._variants_search(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._variants_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("variants".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("variantsets", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._variantsets_delete(opt, dry_run, &mut err); + }, + ("export", Some(opt)) => { + call_result = self._variantsets_export(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._variantsets_get(opt, dry_run, &mut err); + }, + ("import-variants", Some(opt)) => { + call_result = self._variantsets_import_variants(opt, dry_run, &mut err); + }, + ("merge-variants", Some(opt)) => { + call_result = self._variantsets_merge_variants(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._variantsets_patch(opt, dry_run, &mut err); + }, + ("search", Some(opt)) => { + call_result = self._variantsets_search(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._variantsets_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("variantsets".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_annotations { - if self.opt.cmd_batch_create { - call_result = self._annotations_batch_create(dry_run, &mut err); - } else if self.opt.cmd_create { - call_result = self._annotations_create(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._annotations_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._annotations_get(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._annotations_patch(dry_run, &mut err); - } else if self.opt.cmd_search { - call_result = self._annotations_search(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._annotations_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_callsets { - if self.opt.cmd_create { - call_result = self._callsets_create(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._callsets_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._callsets_get(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._callsets_patch(dry_run, &mut err); - } else if self.opt.cmd_search { - call_result = self._callsets_search(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._callsets_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_datasets { - if self.opt.cmd_create { - call_result = self._datasets_create(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._datasets_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._datasets_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._datasets_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._datasets_patch(dry_run, &mut err); - } else if self.opt.cmd_undelete { - call_result = self._datasets_undelete(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._datasets_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_experimental { - if self.opt.cmd_jobs_create { - call_result = self._experimental_jobs_create(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_jobs { - if self.opt.cmd_cancel { - call_result = self._jobs_cancel(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._jobs_get(dry_run, &mut err); - } else if self.opt.cmd_search { - call_result = self._jobs_search(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_readgroupsets { - if self.opt.cmd_align { - call_result = self._readgroupsets_align(dry_run, &mut err); - } else if self.opt.cmd_call { - call_result = self._readgroupsets_call(dry_run, &mut err); - } else if self.opt.cmd_coveragebuckets_list { - call_result = self._readgroupsets_coveragebuckets_list(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._readgroupsets_delete(dry_run, &mut err); - } else if self.opt.cmd_export { - call_result = self._readgroupsets_export(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._readgroupsets_get(dry_run, &mut err); - } else if self.opt.cmd_import { - call_result = self._readgroupsets_import(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._readgroupsets_patch(dry_run, &mut err); - } else if self.opt.cmd_search { - call_result = self._readgroupsets_search(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._readgroupsets_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_reads { - if self.opt.cmd_search { - call_result = self._reads_search(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_references { - if self.opt.cmd_bases_list { - call_result = self._references_bases_list(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._references_get(dry_run, &mut err); - } else if self.opt.cmd_search { - call_result = self._references_search(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_referencesets { - if self.opt.cmd_get { - call_result = self._referencesets_get(dry_run, &mut err); - } else if self.opt.cmd_search { - call_result = self._referencesets_search(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_streaming_readstore { - if self.opt.cmd_streamreads { - call_result = self._streaming_readstore_streamreads(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_variants { - if self.opt.cmd_create { - call_result = self._variants_create(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._variants_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._variants_get(dry_run, &mut err); - } else if self.opt.cmd_search { - call_result = self._variants_search(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._variants_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_variantsets { - if self.opt.cmd_delete { - call_result = self._variantsets_delete(dry_run, &mut err); - } else if self.opt.cmd_export { - call_result = self._variantsets_export(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._variantsets_get(dry_run, &mut err); - } else if self.opt.cmd_import_variants { - call_result = self._variantsets_import_variants(dry_run, &mut err); - } else if self.opt.cmd_merge_variants { - call_result = self._variantsets_merge_variants(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._variantsets_patch(dry_run, &mut err); - } else if self.opt.cmd_search { - call_result = self._variantsets_search(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._variantsets_update(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -4992,7 +5256,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -5005,7 +5269,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -5015,37 +5279,1559 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Genomics::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("annotation-sets", "methods: 'create', 'delete', 'get', 'patch', 'search' and 'update'", vec![ + ("create", + Some(r##"Creates a new annotation set. Caller must have WRITE permission for the associated dataset."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/annotation-sets_create", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes an annotation set. Caller must have WRITE permission for the associated annotation set."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/annotation-sets_delete", + vec![ + (Some(r##"annotation-set-id"##), + None, + Some(r##"The ID of the annotation set to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets an annotation set. Caller must have READ permission for the associated dataset."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/annotation-sets_get", + vec![ + (Some(r##"annotation-set-id"##), + None, + Some(r##"The ID of the annotation set to be retrieved."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an annotation set. The update must respect all mutability restrictions and other invariants described on the annotation set resource. Caller must have WRITE permission for the associated dataset. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/annotation-sets_patch", + vec![ + (Some(r##"annotation-set-id"##), + None, + Some(r##"The ID of the annotation set to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("search", + Some(r##"Searches for annotation sets that match the given criteria. Results are returned in a deterministic order. Caller must have READ permission for the queried datasets."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/annotation-sets_search", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an annotation set. The update must respect all mutability restrictions and other invariants described on the annotation set resource. Caller must have WRITE permission for the associated dataset."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/annotation-sets_update", + vec![ + (Some(r##"annotation-set-id"##), + None, + Some(r##"The ID of the annotation set to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("annotations", "methods: 'batch-create', 'create', 'delete', 'get', 'patch', 'search' and 'update'", vec![ + ("batch-create", + Some(r##"Creates one or more new annotations atomically. All annotations must belong to the same annotation set. Caller must have WRITE permission for this annotation set. For optimal performance, batch positionally adjacent annotations together. + + + If the request has a systemic issue, such as an attempt to write to an inaccessible annotation set, the entire RPC will fail accordingly. For lesser data issues, when possible an error will be isolated to the corresponding batch entry in the response; the remaining well formed annotations will be created normally."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/annotations_batch-create", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("create", + Some(r##"Creates a new annotation. Caller must have WRITE permission for the associated annotation set."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/annotations_create", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes an annotation. Caller must have WRITE permission for the associated annotation set."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/annotations_delete", + vec![ + (Some(r##"annotation-id"##), + None, + Some(r##"The ID of the annotation set to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets an annotation. Caller must have READ permission for the associated annotation set."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/annotations_get", + vec![ + (Some(r##"annotation-id"##), + None, + Some(r##"The ID of the annotation set to be retrieved."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an annotation. The update must respect all mutability restrictions and other invariants described on the annotation resource. Caller must have WRITE permission for the associated dataset. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/annotations_patch", + vec![ + (Some(r##"annotation-id"##), + None, + Some(r##"The ID of the annotation set to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("search", + Some(r##"Searches for annotations that match the given criteria. Results are returned ordered by start position. Annotations that have matching start positions are ordered deterministically. Caller must have READ permission for the queried annotation sets."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/annotations_search", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an annotation. The update must respect all mutability restrictions and other invariants described on the annotation resource. Caller must have WRITE permission for the associated dataset."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/annotations_update", + vec![ + (Some(r##"annotation-id"##), + None, + Some(r##"The ID of the annotation set to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("callsets", "methods: 'create', 'delete', 'get', 'patch', 'search' and 'update'", vec![ + ("create", + Some(r##"Creates a new call set."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/callsets_create", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes a call set."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/callsets_delete", + vec![ + (Some(r##"call-set-id"##), + None, + Some(r##"The ID of the call set to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets a call set by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/callsets_get", + vec![ + (Some(r##"call-set-id"##), + None, + Some(r##"The ID of the call set."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a call set. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/callsets_patch", + vec![ + (Some(r##"call-set-id"##), + None, + Some(r##"The ID of the call set to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("search", + Some(r##"Gets a list of call sets matching the criteria. + + Implements GlobalAllianceApi.searchCallSets."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/callsets_search", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a call set."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/callsets_update", + vec![ + (Some(r##"call-set-id"##), + None, + Some(r##"The ID of the call set to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("datasets", "methods: 'create', 'delete', 'get', 'list', 'patch', 'undelete' and 'update'", vec![ + ("create", + Some(r##"Creates a new dataset."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/datasets_create", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes a dataset."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/datasets_delete", + vec![ + (Some(r##"dataset-id"##), + None, + Some(r##"The ID of the dataset to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets a dataset by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/datasets_get", + vec![ + (Some(r##"dataset-id"##), + None, + Some(r##"The ID of the dataset."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists datasets within a project."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/datasets_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a dataset. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/datasets_patch", + vec![ + (Some(r##"dataset-id"##), + None, + Some(r##"The ID of the dataset to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("undelete", + Some(r##"Undeletes a dataset by restoring a dataset which was deleted via this API. This operation is only possible for a week after the deletion occurred."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/datasets_undelete", + vec![ + (Some(r##"dataset-id"##), + None, + Some(r##"The ID of the dataset to be undeleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a dataset."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/datasets_update", + vec![ + (Some(r##"dataset-id"##), + None, + Some(r##"The ID of the dataset to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("experimental", "methods: 'jobs-create'", vec![ + ("jobs-create", + Some(r##"Creates and asynchronously runs an ad-hoc job. This is an experimental call and may be removed or changed at any time."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/experimental_jobs-create", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("jobs", "methods: 'cancel', 'get' and 'search'", vec![ + ("cancel", + Some(r##"Cancels a job by ID. Note that it is possible for partial results to be generated and stored for cancelled jobs."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/jobs_cancel", + vec![ + (Some(r##"job-id"##), + None, + Some(r##"Required. The ID of the job."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets a job by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/jobs_get", + vec![ + (Some(r##"job-id"##), + None, + Some(r##"Required. The ID of the job."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("search", + Some(r##"Gets a list of jobs matching the criteria."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/jobs_search", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("readgroupsets", "methods: 'align', 'call', 'coveragebuckets-list', 'delete', 'export', 'get', 'import', 'patch', 'search' and 'update'", vec![ + ("align", + Some(r##"Aligns read data from existing read group sets or files from Google Cloud Storage. See the alignment and variant calling documentation for more details."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/readgroupsets_align", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("call", + Some(r##"Calls variants on read data from existing read group sets or files from Google Cloud Storage. See the alignment and variant calling documentation for more details."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/readgroupsets_call", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("coveragebuckets-list", + Some(r##"Lists fixed width coverage buckets for a read group set, each of which correspond to a range of a reference sequence. Each bucket summarizes coverage information across its corresponding genomic range. + + Coverage is defined as the number of reads which are aligned to a given base in the reference sequence. Coverage buckets are available at several precomputed bucket widths, enabling retrieval of various coverage 'zoom levels'. The caller must have READ permissions for the target read group set."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/readgroupsets_coveragebuckets-list", + vec![ + (Some(r##"read-group-set-id"##), + None, + Some(r##"Required. The ID of the read group set over which coverage is requested."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes a read group set."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/readgroupsets_delete", + vec![ + (Some(r##"read-group-set-id"##), + None, + Some(r##"The ID of the read group set to be deleted. The caller must have WRITE permissions to the dataset associated with this read group set."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("export", + Some(r##"Exports read group sets to a BAM file in Google Cloud Storage. + + Note that currently there may be some differences between exported BAM files and the original BAM file at the time of import. In particular, comments in the input file header will not be preserved, some custom tags will be converted to strings, and original reference sequence order is not necessarily preserved."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/readgroupsets_export", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Gets a read group set by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/readgroupsets_get", + vec![ + (Some(r##"read-group-set-id"##), + None, + Some(r##"The ID of the read group set."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("import", + Some(r##"Creates read group sets by asynchronously importing the provided information. + + Note that currently comments in the input file header are not imported and some custom tags will be converted to strings, rather than preserving tag types. The caller must have WRITE permissions to the dataset."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/readgroupsets_import", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a read group set. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/readgroupsets_patch", + vec![ + (Some(r##"read-group-set-id"##), + None, + Some(r##"The ID of the read group set to be updated. The caller must have WRITE permissions to the dataset associated with this read group set."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("search", + Some(r##"Searches for read group sets matching the criteria. + + Implements GlobalAllianceApi.searchReadGroupSets."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/readgroupsets_search", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a read group set."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/readgroupsets_update", + vec![ + (Some(r##"read-group-set-id"##), + None, + Some(r##"The ID of the read group set to be updated. The caller must have WRITE permissions to the dataset associated with this read group set."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("reads", "methods: 'search'", vec![ + ("search", + Some(r##"Gets a list of reads for one or more read group sets. Reads search operates over a genomic coordinate space of reference sequence & position defined over the reference sequences to which the requested read group sets are aligned. + + If a target positional range is specified, search returns all reads whose alignment to the reference genome overlap the range. A query which specifies only read group set IDs yields all reads in those read group sets, including unmapped reads. + + All reads returned (including reads on subsequent pages) are ordered by genomic coordinate (reference sequence & position). Reads with equivalent genomic coordinates are returned in a deterministic order. + + Implements GlobalAllianceApi.searchReads."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/reads_search", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("references", "methods: 'bases-list', 'get' and 'search'", vec![ + ("bases-list", + Some(r##"Lists the bases in a reference, optionally restricted to a range. + + Implements GlobalAllianceApi.getReferenceBases."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/references_bases-list", + vec![ + (Some(r##"reference-id"##), + None, + Some(r##"The ID of the reference."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Gets a reference. + + Implements GlobalAllianceApi.getReference."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/references_get", + vec![ + (Some(r##"reference-id"##), + None, + Some(r##"The ID of the reference."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("search", + Some(r##"Searches for references which match the given criteria. + + Implements GlobalAllianceApi.searchReferences."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/references_search", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("referencesets", "methods: 'get' and 'search'", vec![ + ("get", + Some(r##"Gets a reference set. + + Implements GlobalAllianceApi.getReferenceSet."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/referencesets_get", + vec![ + (Some(r##"reference-set-id"##), + None, + Some(r##"The ID of the reference set."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("search", + Some(r##"Searches for reference sets which match the given criteria. + + Implements GlobalAllianceApi.searchReferenceSets."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/referencesets_search", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("streaming-readstore", "methods: 'streamreads'", vec![ + ("streamreads", + Some(r##"Gets a stream of reads for one or more read group sets. Reads search operates over a genomic coordinate space of reference sequence & position defined over the reference sequences to which the requested read group sets are aligned. + + If a target positional range is specified, all reads whose alignment to the reference genome overlap the range are returned. + + All reads returned are ordered by genomic coordinate (reference sequence & position). Reads with equivalent genomic coordinates are returned in a deterministic order."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/streaming-readstore_streamreads", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("variants", "methods: 'create', 'delete', 'get', 'search' and 'update'", vec![ + ("create", + Some(r##"Creates a new variant."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/variants_create", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes a variant."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/variants_delete", + vec![ + (Some(r##"variant-id"##), + None, + Some(r##"The ID of the variant to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets a variant by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/variants_get", + vec![ + (Some(r##"variant-id"##), + None, + Some(r##"The ID of the variant."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("search", + Some(r##"Gets a list of variants matching the criteria. + + Implements GlobalAllianceApi.searchVariants."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/variants_search", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a variant's names and info fields. All other modifications are silently ignored. Returns the modified variant without its calls."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/variants_update", + vec![ + (Some(r##"variant-id"##), + None, + Some(r##"The ID of the variant to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("variantsets", "methods: 'delete', 'export', 'get', 'import-variants', 'merge-variants', 'patch', 'search' and 'update'", vec![ + ("delete", + Some(r##"Deletes the contents of a variant set. The variant set object is not deleted."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/variantsets_delete", + vec![ + (Some(r##"variant-set-id"##), + None, + Some(r##"The ID of the variant set to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("export", + Some(r##"Exports variant set data to an external destination."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/variantsets_export", + vec![ + (Some(r##"variant-set-id"##), + None, + Some(r##"Required. The ID of the variant set that contains variant data which should be exported. The caller must have READ access to this variant set."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Gets a variant set by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/variantsets_get", + vec![ + (Some(r##"variant-set-id"##), + None, + Some(r##"Required. The ID of the variant set."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("import-variants", + Some(r##"Creates variant data by asynchronously importing the provided information. + + The variants for import will be merged with any existing data and each other according to the behavior of mergeVariants. In particular, this means for merged VCF variants that have conflicting INFO fields, some data will be arbitrarily discarded. As a special case, for single-sample VCF files, QUAL and FILTER fields will be moved to the call level; these are sometimes interpreted in a call-specific context. Imported VCF headers are appended to the metadata already in a variant set."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/variantsets_import-variants", + vec![ + (Some(r##"variant-set-id"##), + None, + Some(r##"Required. The variant set to which variant data should be imported."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("merge-variants", + Some(r##"Merges the given variants with existing variants. Each variant will be merged with an existing variant that matches its reference sequence, start, end, reference bases, and alternative bases. If no such variant exists, a new one will be created. + + When variants are merged, the call information from the new variant is added to the existing variant, and other fields (such as key/value pairs) are discarded."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/variantsets_merge-variants", + vec![ + (Some(r##"variant-set-id"##), + None, + Some(r##"The destination variant set."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("patch", + Some(r##"Updates a variant set's metadata. All other modifications are silently ignored. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/variantsets_patch", + vec![ + (Some(r##"variant-set-id"##), + None, + Some(r##"The ID of the variant to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("search", + Some(r##"Returns a list of all variant sets matching search criteria. + + Implements GlobalAllianceApi.searchVariantSets."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/variantsets_search", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a variant set's metadata. All other modifications are silently ignored."##), + "Details at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli/variantsets_update", + vec![ + (Some(r##"variant-set-id"##), + None, + Some(r##"The ID of the variant to be updated."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("genomics1-beta2") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150326") + .about("Provides access to Genomics data.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_genomics1_beta2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/genomics1_beta2/Cargo.toml b/gen/genomics1_beta2/Cargo.toml index 3a9673c90d..162808c952 100644 --- a/gen/genomics1_beta2/Cargo.toml +++ b/gen/genomics1_beta2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-genomics1_beta2" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with genomics (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/genomics1_beta2" @@ -15,9 +15,10 @@ keywords = ["genomics", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/genomics1_beta2/README.md b/gen/genomics1_beta2/README.md index 981d6dff36..fb60687b09 100644 --- a/gen/genomics1_beta2/README.md +++ b/gen/genomics1_beta2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-genomics1_beta2` library allows access to all features of the *Google genomics* service. -This documentation was generated from *genomics* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *genomics:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *genomics* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *genomics:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *genomics* *v1_beta2* API can be found at the [official documentation site](https://developers.google.com/genomics/v1beta2/reference). @@ -193,7 +193,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_genomics1_beta2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_genomics1_beta2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/genomics1_beta2/src/cmn.rs b/gen/genomics1_beta2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/genomics1_beta2/src/cmn.rs +++ b/gen/genomics1_beta2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/genomics1_beta2/src/lib.rs b/gen/genomics1_beta2/src/lib.rs index 0d7975f794..1a16c7e43e 100644 --- a/gen/genomics1_beta2/src/lib.rs +++ b/gen/genomics1_beta2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *genomics* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *genomics:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *genomics* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *genomics:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *genomics* *v1_beta2* API can be found at the //! [official documentation site](https://developers.google.com/genomics/v1beta2/reference). @@ -194,7 +194,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -203,7 +203,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -219,6 +218,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -353,7 +353,7 @@ impl<'a, C, A> Genomics<C, A> Genomics { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -398,7 +398,7 @@ impl<'a, C, A> Genomics<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -4120,6 +4120,7 @@ impl<'a, C, A> DatasetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Dataset)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4175,11 +4176,20 @@ impl<'a, C, A> DatasetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4202,7 +4212,7 @@ impl<'a, C, A> DatasetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4382,6 +4392,7 @@ impl<'a, C, A> DatasetCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Dataset)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4412,11 +4423,20 @@ impl<'a, C, A> DatasetCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4439,7 +4459,7 @@ impl<'a, C, A> DatasetCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4657,7 +4677,7 @@ impl<'a, C, A> DatasetDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4679,7 +4699,7 @@ impl<'a, C, A> DatasetDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4886,7 +4906,7 @@ impl<'a, C, A> DatasetUndeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4908,7 +4928,7 @@ impl<'a, C, A> DatasetUndeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5125,7 +5145,7 @@ impl<'a, C, A> DatasetGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5147,7 +5167,7 @@ impl<'a, C, A> DatasetGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5353,7 +5373,7 @@ impl<'a, C, A> DatasetListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5375,7 +5395,7 @@ impl<'a, C, A> DatasetListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5555,6 +5575,7 @@ impl<'a, C, A> DatasetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Dataset)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5610,11 +5631,20 @@ impl<'a, C, A> DatasetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5637,7 +5667,7 @@ impl<'a, C, A> DatasetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5865,7 +5895,7 @@ impl<'a, C, A> JobCancelCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5887,7 +5917,7 @@ impl<'a, C, A> JobCancelCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6094,7 +6124,7 @@ impl<'a, C, A> JobGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth2 if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6116,7 +6146,7 @@ impl<'a, C, A> JobGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth2 access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6284,6 +6314,7 @@ impl<'a, C, A> JobSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SearchJobsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6314,11 +6345,20 @@ impl<'a, C, A> JobSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6341,7 +6381,7 @@ impl<'a, C, A> JobSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6513,6 +6553,7 @@ impl<'a, C, A> ReferencesetSearchCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SearchReferenceSetsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6543,11 +6584,20 @@ impl<'a, C, A> ReferencesetSearchCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6570,7 +6620,7 @@ impl<'a, C, A> ReferencesetSearchCall<'a, C, A> where C: BorrowMut<hyper::Client request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6791,7 +6841,7 @@ impl<'a, C, A> ReferencesetGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6813,7 +6863,7 @@ impl<'a, C, A> ReferencesetGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7029,7 +7079,7 @@ impl<'a, C, A> CallsetDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7051,7 +7101,7 @@ impl<'a, C, A> CallsetDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7211,6 +7261,7 @@ impl<'a, C, A> CallsetSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SearchCallSetsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7241,11 +7292,20 @@ impl<'a, C, A> CallsetSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7268,7 +7328,7 @@ impl<'a, C, A> CallsetSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7439,6 +7499,7 @@ impl<'a, C, A> CallsetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CallSet)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7494,11 +7555,20 @@ impl<'a, C, A> CallsetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7521,7 +7591,7 @@ impl<'a, C, A> CallsetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7701,6 +7771,7 @@ impl<'a, C, A> CallsetCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CallSet)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7731,11 +7802,20 @@ impl<'a, C, A> CallsetCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7758,7 +7838,7 @@ impl<'a, C, A> CallsetCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7977,7 +8057,7 @@ impl<'a, C, A> CallsetGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7999,7 +8079,7 @@ impl<'a, C, A> CallsetGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8168,6 +8248,7 @@ impl<'a, C, A> CallsetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CallSet)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8223,11 +8304,20 @@ impl<'a, C, A> CallsetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8250,7 +8340,7 @@ impl<'a, C, A> CallsetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8433,6 +8523,7 @@ impl<'a, C, A> StreamingReadstoreStreamreadCall<'a, C, A> where C: BorrowMut<hyp /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, StreamReadsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8472,11 +8563,20 @@ impl<'a, C, A> StreamingReadstoreStreamreadCall<'a, C, A> where C: BorrowMut<hyp if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8485,7 +8585,7 @@ impl<'a, C, A> StreamingReadstoreStreamreadCall<'a, C, A> where C: BorrowMut<hyp request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -8644,6 +8744,7 @@ impl<'a, C, A> ReadSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SearchReadsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8674,11 +8775,20 @@ impl<'a, C, A> ReadSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8701,7 +8811,7 @@ impl<'a, C, A> ReadSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8873,6 +8983,7 @@ impl<'a, C, A> ReadgroupsetExportCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ExportReadGroupSetsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8903,11 +9014,20 @@ impl<'a, C, A> ReadgroupsetExportCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8930,7 +9050,7 @@ impl<'a, C, A> ReadgroupsetExportCall<'a, C, A> where C: BorrowMut<hyper::Client request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9101,6 +9221,7 @@ impl<'a, C, A> ReadgroupsetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client> /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ReadGroupSet)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9156,11 +9277,20 @@ impl<'a, C, A> ReadgroupsetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9183,7 +9313,7 @@ impl<'a, C, A> ReadgroupsetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client> request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9363,6 +9493,7 @@ impl<'a, C, A> ReadgroupsetCallCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CallReadGroupSetsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9393,11 +9524,20 @@ impl<'a, C, A> ReadgroupsetCallCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9420,7 +9560,7 @@ impl<'a, C, A> ReadgroupsetCallCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9592,6 +9732,7 @@ impl<'a, C, A> ReadgroupsetImportCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ImportReadGroupSetsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9622,11 +9763,20 @@ impl<'a, C, A> ReadgroupsetImportCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9649,7 +9799,7 @@ impl<'a, C, A> ReadgroupsetImportCall<'a, C, A> where C: BorrowMut<hyper::Client request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9819,6 +9969,7 @@ impl<'a, C, A> ReadgroupsetAlignCall<'a, C, A> where C: BorrowMut<hyper::Client> /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AlignReadGroupSetsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9849,11 +10000,20 @@ impl<'a, C, A> ReadgroupsetAlignCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9876,7 +10036,7 @@ impl<'a, C, A> ReadgroupsetAlignCall<'a, C, A> where C: BorrowMut<hyper::Client> request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -10095,7 +10255,7 @@ impl<'a, C, A> ReadgroupsetGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10117,7 +10277,7 @@ impl<'a, C, A> ReadgroupsetGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10286,6 +10446,7 @@ impl<'a, C, A> ReadgroupsetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ReadGroupSet)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10341,11 +10502,20 @@ impl<'a, C, A> ReadgroupsetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10368,7 +10538,7 @@ impl<'a, C, A> ReadgroupsetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -10629,7 +10799,7 @@ impl<'a, C, A> ReadgroupsetCoveragebucketListCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10651,7 +10821,7 @@ impl<'a, C, A> ReadgroupsetCoveragebucketListCall<'a, C, A> where C: BorrowMut<h access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10909,7 +11079,7 @@ impl<'a, C, A> ReadgroupsetDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10931,7 +11101,7 @@ impl<'a, C, A> ReadgroupsetDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11091,6 +11261,7 @@ impl<'a, C, A> ReadgroupsetSearchCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SearchReadGroupSetsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11121,11 +11292,20 @@ impl<'a, C, A> ReadgroupsetSearchCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11148,7 +11328,7 @@ impl<'a, C, A> ReadgroupsetSearchCall<'a, C, A> where C: BorrowMut<hyper::Client request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11389,7 +11569,7 @@ impl<'a, C, A> ReferenceBaseListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11411,7 +11591,7 @@ impl<'a, C, A> ReferenceBaseListCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11609,6 +11789,7 @@ impl<'a, C, A> ReferenceSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SearchReferencesResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11639,11 +11820,20 @@ impl<'a, C, A> ReferenceSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11666,7 +11856,7 @@ impl<'a, C, A> ReferenceSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11887,7 +12077,7 @@ impl<'a, C, A> ReferenceGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11909,7 +12099,7 @@ impl<'a, C, A> ReferenceGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12126,7 +12316,7 @@ impl<'a, C, A> AnnotationSetGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12148,7 +12338,7 @@ impl<'a, C, A> AnnotationSetGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12317,6 +12507,7 @@ impl<'a, C, A> AnnotationSetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AnnotationSet)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12372,11 +12563,20 @@ impl<'a, C, A> AnnotationSetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12399,7 +12599,7 @@ impl<'a, C, A> AnnotationSetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clien request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -12579,6 +12779,7 @@ impl<'a, C, A> AnnotationSetCreateCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AnnotationSet)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12609,11 +12810,20 @@ impl<'a, C, A> AnnotationSetCreateCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12636,7 +12846,7 @@ impl<'a, C, A> AnnotationSetCreateCall<'a, C, A> where C: BorrowMut<hyper::Clien request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -12806,6 +13016,7 @@ impl<'a, C, A> AnnotationSetSearchCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SearchAnnotationSetsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12836,11 +13047,20 @@ impl<'a, C, A> AnnotationSetSearchCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12863,7 +13083,7 @@ impl<'a, C, A> AnnotationSetSearchCall<'a, C, A> where C: BorrowMut<hyper::Clien request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -13034,6 +13254,7 @@ impl<'a, C, A> AnnotationSetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, AnnotationSet)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13089,11 +13310,20 @@ impl<'a, C, A> AnnotationSetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13116,7 +13346,7 @@ impl<'a, C, A> AnnotationSetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -13344,7 +13574,7 @@ impl<'a, C, A> AnnotationSetDeleteCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13366,7 +13596,7 @@ impl<'a, C, A> AnnotationSetDeleteCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -13526,6 +13756,7 @@ impl<'a, C, A> VariantSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SearchVariantsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13556,11 +13787,20 @@ impl<'a, C, A> VariantSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13583,7 +13823,7 @@ impl<'a, C, A> VariantSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -13801,7 +14041,7 @@ impl<'a, C, A> VariantDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13823,7 +14063,7 @@ impl<'a, C, A> VariantDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -14030,7 +14270,7 @@ impl<'a, C, A> VariantGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14052,7 +14292,7 @@ impl<'a, C, A> VariantGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -14220,6 +14460,7 @@ impl<'a, C, A> VariantCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Variant)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14250,11 +14491,20 @@ impl<'a, C, A> VariantCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14277,7 +14527,7 @@ impl<'a, C, A> VariantCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -14448,6 +14698,7 @@ impl<'a, C, A> VariantUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Variant)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14503,11 +14754,20 @@ impl<'a, C, A> VariantUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14530,7 +14790,7 @@ impl<'a, C, A> VariantUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -14711,6 +14971,7 @@ impl<'a, C, A> AnnotationUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Annotation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14766,11 +15027,20 @@ impl<'a, C, A> AnnotationUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14793,7 +15063,7 @@ impl<'a, C, A> AnnotationUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -15022,7 +15292,7 @@ impl<'a, C, A> AnnotationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15044,7 +15314,7 @@ impl<'a, C, A> AnnotationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -15212,6 +15482,7 @@ impl<'a, C, A> AnnotationSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SearchAnnotationsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15242,11 +15513,20 @@ impl<'a, C, A> AnnotationSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15269,7 +15549,7 @@ impl<'a, C, A> AnnotationSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -15487,7 +15767,7 @@ impl<'a, C, A> AnnotationDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -15509,7 +15789,7 @@ impl<'a, C, A> AnnotationDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -15668,6 +15948,7 @@ impl<'a, C, A> AnnotationPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Annotation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15723,11 +16004,20 @@ impl<'a, C, A> AnnotationPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15750,7 +16040,7 @@ impl<'a, C, A> AnnotationPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -15930,6 +16220,7 @@ impl<'a, C, A> AnnotationCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Annotation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15960,11 +16251,20 @@ impl<'a, C, A> AnnotationCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15987,7 +16287,7 @@ impl<'a, C, A> AnnotationCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -16160,6 +16460,7 @@ impl<'a, C, A> AnnotationBatchCreateCall<'a, C, A> where C: BorrowMut<hyper::Cli /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, BatchAnnotationsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -16190,11 +16491,20 @@ impl<'a, C, A> AnnotationBatchCreateCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -16217,7 +16527,7 @@ impl<'a, C, A> AnnotationBatchCreateCall<'a, C, A> where C: BorrowMut<hyper::Cli request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -16387,6 +16697,7 @@ impl<'a, C, A> ExperimentalJobCreateCall<'a, C, A> where C: BorrowMut<hyper::Cli /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ExperimentalCreateJobResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -16417,11 +16728,20 @@ impl<'a, C, A> ExperimentalJobCreateCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -16444,7 +16764,7 @@ impl<'a, C, A> ExperimentalJobCreateCall<'a, C, A> where C: BorrowMut<hyper::Cli request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -16615,6 +16935,7 @@ impl<'a, C, A> VariantsetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, VariantSet)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -16670,11 +16991,20 @@ impl<'a, C, A> VariantsetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -16697,7 +17027,7 @@ impl<'a, C, A> VariantsetUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -16878,6 +17208,7 @@ impl<'a, C, A> VariantsetExportCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ExportVariantSetResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -16933,11 +17264,20 @@ impl<'a, C, A> VariantsetExportCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -16960,7 +17300,7 @@ impl<'a, C, A> VariantsetExportCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -17141,6 +17481,7 @@ impl<'a, C, A> VariantsetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, VariantSet)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17196,11 +17537,20 @@ impl<'a, C, A> VariantsetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17223,7 +17573,7 @@ impl<'a, C, A> VariantsetPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -17405,6 +17755,7 @@ impl<'a, C, A> VariantsetSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SearchVariantSetsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17435,11 +17786,20 @@ impl<'a, C, A> VariantsetSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17462,7 +17822,7 @@ impl<'a, C, A> VariantsetSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -17681,7 +18041,7 @@ impl<'a, C, A> VariantsetGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17703,7 +18063,7 @@ impl<'a, C, A> VariantsetGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -17874,6 +18234,7 @@ impl<'a, C, A> VariantsetMergeVariantCall<'a, C, A> where C: BorrowMut<hyper::Cl /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17928,11 +18289,20 @@ impl<'a, C, A> VariantsetMergeVariantCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17955,7 +18325,7 @@ impl<'a, C, A> VariantsetMergeVariantCall<'a, C, A> where C: BorrowMut<hyper::Cl request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -18173,7 +18543,7 @@ impl<'a, C, A> VariantsetDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18195,7 +18565,7 @@ impl<'a, C, A> VariantsetDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -18356,6 +18726,7 @@ impl<'a, C, A> VariantsetImportVariantCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ImportVariantsResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -18411,11 +18782,20 @@ impl<'a, C, A> VariantsetImportVariantCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -18438,7 +18818,7 @@ impl<'a, C, A> VariantsetImportVariantCall<'a, C, A> where C: BorrowMut<hyper::C request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) diff --git a/gen/gmail1-cli/Cargo.toml b/gen/gmail1-cli/Cargo.toml index 58b243c8a7..51e23d29c2 100644 --- a/gen/gmail1-cli/Cargo.toml +++ b/gen/gmail1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-gmail1-cli" -version = "0.1.0+20150303" +version = "0.2.0+20150303" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with gmail (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/gmail1-cli" @@ -17,15 +17,14 @@ keywords = ["gmail", "google", "cli"] name = "gmail1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-gmail1] path = "../gmail1" diff --git a/gen/gmail1-cli/README.md b/gen/gmail1-cli/README.md index 8af4cc54c7..6f7f1733a9 100644 --- a/gen/gmail1-cli/README.md +++ b/gen/gmail1-cli/README.md @@ -10,50 +10,52 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *gmail* API can be found at the +[official documentation site](https://developers.google.com/gmail/api/). + # Usage -This documentation was generated from the *gmail* API at revision *20150303*. The CLI is at version *0.1.0*. +This documentation was generated from the *gmail* API at revision *20150303*. The CLI is at version *0.2.0*. ```bash - gmail1 [options] users drafts-create <user-id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - gmail1 [options] users drafts-delete <user-id> <id> [-p <v>...] - gmail1 [options] users drafts-get <user-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users drafts-list <user-id> [-p <v>...] [-o <out>] - gmail1 [options] users drafts-send <user-id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - gmail1 [options] users drafts-update <user-id> <id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - gmail1 [options] users get-profile <user-id> [-p <v>...] [-o <out>] - gmail1 [options] users history-list <user-id> [-p <v>...] [-o <out>] - gmail1 [options] users labels-create <user-id> -r <kv>... [-p <v>...] [-o <out>] - gmail1 [options] users labels-delete <user-id> <id> [-p <v>...] - gmail1 [options] users labels-get <user-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users labels-list <user-id> [-p <v>...] [-o <out>] - gmail1 [options] users labels-patch <user-id> <id> -r <kv>... [-p <v>...] [-o <out>] - gmail1 [options] users labels-update <user-id> <id> -r <kv>... [-p <v>...] [-o <out>] - gmail1 [options] users messages-attachments-get <user-id> <message-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users messages-delete <user-id> <id> [-p <v>...] - gmail1 [options] users messages-get <user-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users messages-import <user-id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - gmail1 [options] users messages-insert <user-id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - gmail1 [options] users messages-list <user-id> [-p <v>...] [-o <out>] - gmail1 [options] users messages-modify <user-id> <id> -r <kv>... [-p <v>...] [-o <out>] - gmail1 [options] users messages-send <user-id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - gmail1 [options] users messages-trash <user-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users messages-untrash <user-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users threads-delete <user-id> <id> [-p <v>...] - gmail1 [options] users threads-get <user-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users threads-list <user-id> [-p <v>...] [-o <out>] - gmail1 [options] users threads-modify <user-id> <id> -r <kv>... [-p <v>...] [-o <out>] - gmail1 [options] users threads-trash <user-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users threads-untrash <user-id> <id> [-p <v>...] [-o <out>] +gmail1 [options] + users + drafts-create <user-id> (-r <kv>)... (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + drafts-delete <user-id> <id> [-p <v>]... + drafts-get <user-id> <id> [-p <v>]... [-o <out>] + drafts-list <user-id> [-p <v>]... [-o <out>] + drafts-send <user-id> (-r <kv>)... (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + drafts-update <user-id> <id> (-r <kv>)... (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + get-profile <user-id> [-p <v>]... [-o <out>] + history-list <user-id> [-p <v>]... [-o <out>] + labels-create <user-id> (-r <kv>)... [-p <v>]... [-o <out>] + labels-delete <user-id> <id> [-p <v>]... + labels-get <user-id> <id> [-p <v>]... [-o <out>] + labels-list <user-id> [-p <v>]... [-o <out>] + labels-patch <user-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + labels-update <user-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + messages-attachments-get <user-id> <message-id> <id> [-p <v>]... [-o <out>] + messages-delete <user-id> <id> [-p <v>]... + messages-get <user-id> <id> [-p <v>]... [-o <out>] + messages-import <user-id> (-r <kv>)... (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + messages-insert <user-id> (-r <kv>)... (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + messages-list <user-id> [-p <v>]... [-o <out>] + messages-modify <user-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + messages-send <user-id> (-r <kv>)... (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + messages-trash <user-id> <id> [-p <v>]... [-o <out>] + messages-untrash <user-id> <id> [-p <v>]... [-o <out>] + threads-delete <user-id> <id> [-p <v>]... + threads-get <user-id> <id> [-p <v>]... [-o <out>] + threads-list <user-id> [-p <v>]... [-o <out>] + threads-modify <user-id> <id> (-r <kv>)... [-p <v>]... [-o <out>] + threads-trash <user-id> <id> [-p <v>]... [-o <out>] + threads-untrash <user-id> <id> [-p <v>]... [-o <out>] gmail1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_gmail1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/gmail1-cli/mkdocs.yml b/gen/gmail1-cli/mkdocs.yml index 920533c106..f2d6c17cad 100644 --- a/gen/gmail1-cli/mkdocs.yml +++ b/gen/gmail1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: gmail v0.1.0+20150303 +site_name: gmail v0.2.0+20150303 site_url: http://byron.github.io/google-apis-rs/google-gmail1-cli site_description: Write integrating applications with bcore diff --git a/gen/gmail1-cli/src/cmn.rs b/gen/gmail1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/gmail1-cli/src/cmn.rs +++ b/gen/gmail1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/gmail1-cli/src/main.rs b/gen/gmail1-cli/src/main.rs index 2a9f6c576a..1bd5dd187f 100644 --- a/gen/gmail1-cli/src/main.rs +++ b/gen/gmail1-cli/src/main.rs @@ -2,98 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_gmail1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - gmail1 [options] users drafts-create <user-id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - gmail1 [options] users drafts-delete <user-id> <id> [-p <v>...] - gmail1 [options] users drafts-get <user-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users drafts-list <user-id> [-p <v>...] [-o <out>] - gmail1 [options] users drafts-send <user-id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - gmail1 [options] users drafts-update <user-id> <id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - gmail1 [options] users get-profile <user-id> [-p <v>...] [-o <out>] - gmail1 [options] users history-list <user-id> [-p <v>...] [-o <out>] - gmail1 [options] users labels-create <user-id> -r <kv>... [-p <v>...] [-o <out>] - gmail1 [options] users labels-delete <user-id> <id> [-p <v>...] - gmail1 [options] users labels-get <user-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users labels-list <user-id> [-p <v>...] [-o <out>] - gmail1 [options] users labels-patch <user-id> <id> -r <kv>... [-p <v>...] [-o <out>] - gmail1 [options] users labels-update <user-id> <id> -r <kv>... [-p <v>...] [-o <out>] - gmail1 [options] users messages-attachments-get <user-id> <message-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users messages-delete <user-id> <id> [-p <v>...] - gmail1 [options] users messages-get <user-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users messages-import <user-id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - gmail1 [options] users messages-insert <user-id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - gmail1 [options] users messages-list <user-id> [-p <v>...] [-o <out>] - gmail1 [options] users messages-modify <user-id> <id> -r <kv>... [-p <v>...] [-o <out>] - gmail1 [options] users messages-send <user-id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - gmail1 [options] users messages-trash <user-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users messages-untrash <user-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users threads-delete <user-id> <id> [-p <v>...] - gmail1 [options] users threads-get <user-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users threads-list <user-id> [-p <v>...] [-o <out>] - gmail1 [options] users threads-modify <user-id> <id> -r <kv>... [-p <v>...] [-o <out>] - gmail1 [options] users threads-trash <user-id> <id> [-p <v>...] [-o <out>] - gmail1 [options] users threads-untrash <user-id> <id> [-p <v>...] [-o <out>] - gmail1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_gmail1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Gmail<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _users_drafts_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _users_drafts_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Draft::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -188,161 +145,163 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attachment-id", "body", "data", "filename", "history-id", "id", "label-ids", "message", "mime-type", "part-id", "payload", "raw", "size", "size-estimate", "snippet", "thread-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().drafts_create(request, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().drafts_create(request, opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_drafts_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().drafts_delete(&self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _users_drafts_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().drafts_delete(opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _users_drafts_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().drafts_get(&self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _users_drafts_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().drafts_get(opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "format" => { call = call.format(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["format"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_drafts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().drafts_list(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _users_drafts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().drafts_list(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -351,52 +310,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_drafts_send(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_drafts_send(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Draft::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -491,70 +454,69 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attachment-id", "body", "data", "filename", "history-id", "id", "label-ids", "message", "mime-type", "part-id", "payload", "raw", "size", "size-estimate", "snippet", "thread-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().drafts_send(request, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().drafts_send(request, opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() - }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_drafts_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_drafts_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Draft::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -649,114 +611,117 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attachment-id", "body", "data", "filename", "history-id", "id", "label-ids", "message", "mime-type", "part-id", "payload", "raw", "size", "size-estimate", "snippet", "thread-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().drafts_update(request, &self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().drafts_update(request, opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_get_profile(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().get_profile(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _users_get_profile(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().get_profile(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_history_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().history_list(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _users_history_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().history_list(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-history-id" => { @@ -771,52 +736,56 @@ impl Engine { "label-id" => { call = call.label_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "label-id", "start-history-id", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_labels_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_labels_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Label::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -859,196 +828,208 @@ impl Engine { request.messages_unread = Some(arg_from_str(value.unwrap_or("-0"), err, "messages-unread", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "label-list-visibility", "message-list-visibility", "messages-total", "messages-unread", "name", "threads-total", "threads-unread", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().labels_create(request, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().labels_create(request, opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_labels_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().labels_delete(&self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _users_labels_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().labels_delete(opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _users_labels_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().labels_get(&self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _users_labels_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().labels_get(opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_labels_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().labels_list(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _users_labels_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().labels_list(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_labels_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_labels_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Label::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1091,60 +1072,65 @@ impl Engine { request.messages_unread = Some(arg_from_str(value.unwrap_or("-0"), err, "messages-unread", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "label-list-visibility", "message-list-visibility", "messages-total", "messages-unread", "name", "threads-total", "threads-unread", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().labels_patch(request, &self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().labels_patch(request, opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_labels_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_labels_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Label::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1187,148 +1173,156 @@ impl Engine { request.messages_unread = Some(arg_from_str(value.unwrap_or("-0"), err, "messages-unread", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "label-list-visibility", "message-list-visibility", "messages-total", "messages-unread", "name", "threads-total", "threads-unread", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().labels_update(request, &self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().labels_update(request, opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_messages_attachments_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().messages_attachments_get(&self.opt.arg_user_id, &self.opt.arg_message_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _users_messages_attachments_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().messages_attachments_get(opt.value_of("user-id").unwrap_or(""), opt.value_of("message-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_messages_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().messages_delete(&self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _users_messages_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().messages_delete(opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _users_messages_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().messages_get(&self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _users_messages_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().messages_get(opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "metadata-headers" => { @@ -1337,52 +1331,56 @@ impl Engine { "format" => { call = call.format(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["metadata-headers", "format"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_messages_import(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_messages_import(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Message::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1465,12 +1463,13 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attachment-id", "body", "data", "filename", "history-id", "id", "label-ids", "mime-type", "part-id", "payload", "raw", "size", "size-estimate", "snippet", "thread-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().messages_import(request, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().messages_import(request, opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "process-for-calendar" => { @@ -1485,62 +1484,60 @@ impl Engine { "deleted" => { call = call.deleted(arg_from_str(value.unwrap_or("false"), err, "deleted", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["process-for-calendar", "deleted", "internal-date-source", "never-mark-spam"] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() - }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_messages_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_messages_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Message::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1623,12 +1620,13 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attachment-id", "body", "data", "filename", "history-id", "id", "label-ids", "mime-type", "part-id", "payload", "raw", "size", "size-estimate", "snippet", "thread-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().messages_insert(request, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().messages_insert(request, opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "internal-date-source" => { @@ -1637,60 +1635,58 @@ impl Engine { "deleted" => { call = call.deleted(arg_from_str(value.unwrap_or("false"), err, "deleted", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["deleted", "internal-date-source"] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() - }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_messages_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().messages_list(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _users_messages_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().messages_list(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "q" => { @@ -1708,52 +1704,56 @@ impl Engine { "include-spam-trash" => { call = call.include_spam_trash(arg_from_str(value.unwrap_or("false"), err, "include-spam-trash", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["q", "page-token", "include-spam-trash", "max-results", "label-ids"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_messages_modify(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_messages_modify(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ModifyMessageRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1781,60 +1781,65 @@ impl Engine { request.add_label_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["add-label-ids", "remove-label-ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().messages_modify(request, &self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().messages_modify(request, opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_messages_send(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_messages_send(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Message::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1917,204 +1922,210 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attachment-id", "body", "data", "filename", "history-id", "id", "label-ids", "mime-type", "part-id", "payload", "raw", "size", "size-estimate", "snippet", "thread-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().messages_send(request, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().messages_send(request, opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_messages_trash(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().messages_trash(&self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _users_messages_trash(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().messages_trash(opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_messages_untrash(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().messages_untrash(&self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _users_messages_untrash(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().messages_untrash(opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_threads_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().threads_delete(&self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _users_threads_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().threads_delete(opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _users_threads_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().threads_get(&self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _users_threads_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().threads_get(opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "metadata-headers" => { @@ -2123,50 +2134,54 @@ impl Engine { "format" => { call = call.format(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["metadata-headers", "format"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_threads_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().threads_list(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _users_threads_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().threads_list(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "q" => { @@ -2184,52 +2199,56 @@ impl Engine { "include-spam-trash" => { call = call.include_spam_trash(arg_from_str(value.unwrap_or("false"), err, "include-spam-trash", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["q", "page-token", "include-spam-trash", "max-results", "label-ids"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_threads_modify(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_threads_modify(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ModifyThreadRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2257,231 +2276,282 @@ impl Engine { request.add_label_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["add-label-ids", "remove-label-ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().threads_modify(request, &self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().threads_modify(request, opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_threads_trash(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().threads_trash(&self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _users_threads_trash(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().threads_trash(opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_threads_untrash(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().threads_untrash(&self.opt.arg_user_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _users_threads_untrash(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().threads_untrash(opt.value_of("user-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_users { - if self.opt.cmd_drafts_create { - call_result = self._users_drafts_create(dry_run, &mut err); - } else if self.opt.cmd_drafts_delete { - call_result = self._users_drafts_delete(dry_run, &mut err); - } else if self.opt.cmd_drafts_get { - call_result = self._users_drafts_get(dry_run, &mut err); - } else if self.opt.cmd_drafts_list { - call_result = self._users_drafts_list(dry_run, &mut err); - } else if self.opt.cmd_drafts_send { - call_result = self._users_drafts_send(dry_run, &mut err); - } else if self.opt.cmd_drafts_update { - call_result = self._users_drafts_update(dry_run, &mut err); - } else if self.opt.cmd_get_profile { - call_result = self._users_get_profile(dry_run, &mut err); - } else if self.opt.cmd_history_list { - call_result = self._users_history_list(dry_run, &mut err); - } else if self.opt.cmd_labels_create { - call_result = self._users_labels_create(dry_run, &mut err); - } else if self.opt.cmd_labels_delete { - call_result = self._users_labels_delete(dry_run, &mut err); - } else if self.opt.cmd_labels_get { - call_result = self._users_labels_get(dry_run, &mut err); - } else if self.opt.cmd_labels_list { - call_result = self._users_labels_list(dry_run, &mut err); - } else if self.opt.cmd_labels_patch { - call_result = self._users_labels_patch(dry_run, &mut err); - } else if self.opt.cmd_labels_update { - call_result = self._users_labels_update(dry_run, &mut err); - } else if self.opt.cmd_messages_attachments_get { - call_result = self._users_messages_attachments_get(dry_run, &mut err); - } else if self.opt.cmd_messages_delete { - call_result = self._users_messages_delete(dry_run, &mut err); - } else if self.opt.cmd_messages_get { - call_result = self._users_messages_get(dry_run, &mut err); - } else if self.opt.cmd_messages_import { - call_result = self._users_messages_import(dry_run, &mut err); - } else if self.opt.cmd_messages_insert { - call_result = self._users_messages_insert(dry_run, &mut err); - } else if self.opt.cmd_messages_list { - call_result = self._users_messages_list(dry_run, &mut err); - } else if self.opt.cmd_messages_modify { - call_result = self._users_messages_modify(dry_run, &mut err); - } else if self.opt.cmd_messages_send { - call_result = self._users_messages_send(dry_run, &mut err); - } else if self.opt.cmd_messages_trash { - call_result = self._users_messages_trash(dry_run, &mut err); - } else if self.opt.cmd_messages_untrash { - call_result = self._users_messages_untrash(dry_run, &mut err); - } else if self.opt.cmd_threads_delete { - call_result = self._users_threads_delete(dry_run, &mut err); - } else if self.opt.cmd_threads_get { - call_result = self._users_threads_get(dry_run, &mut err); - } else if self.opt.cmd_threads_list { - call_result = self._users_threads_list(dry_run, &mut err); - } else if self.opt.cmd_threads_modify { - call_result = self._users_threads_modify(dry_run, &mut err); - } else if self.opt.cmd_threads_trash { - call_result = self._users_threads_trash(dry_run, &mut err); - } else if self.opt.cmd_threads_untrash { - call_result = self._users_threads_untrash(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("users", Some(opt)) => { + match opt.subcommand() { + ("drafts-create", Some(opt)) => { + call_result = self._users_drafts_create(opt, dry_run, &mut err); + }, + ("drafts-delete", Some(opt)) => { + call_result = self._users_drafts_delete(opt, dry_run, &mut err); + }, + ("drafts-get", Some(opt)) => { + call_result = self._users_drafts_get(opt, dry_run, &mut err); + }, + ("drafts-list", Some(opt)) => { + call_result = self._users_drafts_list(opt, dry_run, &mut err); + }, + ("drafts-send", Some(opt)) => { + call_result = self._users_drafts_send(opt, dry_run, &mut err); + }, + ("drafts-update", Some(opt)) => { + call_result = self._users_drafts_update(opt, dry_run, &mut err); + }, + ("get-profile", Some(opt)) => { + call_result = self._users_get_profile(opt, dry_run, &mut err); + }, + ("history-list", Some(opt)) => { + call_result = self._users_history_list(opt, dry_run, &mut err); + }, + ("labels-create", Some(opt)) => { + call_result = self._users_labels_create(opt, dry_run, &mut err); + }, + ("labels-delete", Some(opt)) => { + call_result = self._users_labels_delete(opt, dry_run, &mut err); + }, + ("labels-get", Some(opt)) => { + call_result = self._users_labels_get(opt, dry_run, &mut err); + }, + ("labels-list", Some(opt)) => { + call_result = self._users_labels_list(opt, dry_run, &mut err); + }, + ("labels-patch", Some(opt)) => { + call_result = self._users_labels_patch(opt, dry_run, &mut err); + }, + ("labels-update", Some(opt)) => { + call_result = self._users_labels_update(opt, dry_run, &mut err); + }, + ("messages-attachments-get", Some(opt)) => { + call_result = self._users_messages_attachments_get(opt, dry_run, &mut err); + }, + ("messages-delete", Some(opt)) => { + call_result = self._users_messages_delete(opt, dry_run, &mut err); + }, + ("messages-get", Some(opt)) => { + call_result = self._users_messages_get(opt, dry_run, &mut err); + }, + ("messages-import", Some(opt)) => { + call_result = self._users_messages_import(opt, dry_run, &mut err); + }, + ("messages-insert", Some(opt)) => { + call_result = self._users_messages_insert(opt, dry_run, &mut err); + }, + ("messages-list", Some(opt)) => { + call_result = self._users_messages_list(opt, dry_run, &mut err); + }, + ("messages-modify", Some(opt)) => { + call_result = self._users_messages_modify(opt, dry_run, &mut err); + }, + ("messages-send", Some(opt)) => { + call_result = self._users_messages_send(opt, dry_run, &mut err); + }, + ("messages-trash", Some(opt)) => { + call_result = self._users_messages_trash(opt, dry_run, &mut err); + }, + ("messages-untrash", Some(opt)) => { + call_result = self._users_messages_untrash(opt, dry_run, &mut err); + }, + ("threads-delete", Some(opt)) => { + call_result = self._users_threads_delete(opt, dry_run, &mut err); + }, + ("threads-get", Some(opt)) => { + call_result = self._users_threads_get(opt, dry_run, &mut err); + }, + ("threads-list", Some(opt)) => { + call_result = self._users_threads_list(opt, dry_run, &mut err); + }, + ("threads-modify", Some(opt)) => { + call_result = self._users_threads_modify(opt, dry_run, &mut err); + }, + ("threads-trash", Some(opt)) => { + call_result = self._users_threads_trash(opt, dry_run, &mut err); + }, + ("threads-untrash", Some(opt)) => { + call_result = self._users_threads_untrash(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("users".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -2494,7 +2564,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2507,7 +2577,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2517,37 +2587,990 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Gmail::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let upload_value_names = ["mode", "file"]; + let arg_data = [ + ("users", "methods: 'drafts-create', 'drafts-delete', 'drafts-get', 'drafts-list', 'drafts-send', 'drafts-update', 'get-profile', 'history-list', 'labels-create', 'labels-delete', 'labels-get', 'labels-list', 'labels-patch', 'labels-update', 'messages-attachments-get', 'messages-delete', 'messages-get', 'messages-import', 'messages-insert', 'messages-list', 'messages-modify', 'messages-send', 'messages-trash', 'messages-untrash', 'threads-delete', 'threads-get', 'threads-list', 'threads-modify', 'threads-trash' and 'threads-untrash'", vec![ + ("drafts-create", + Some(r##"Creates a new draft with the DRAFT label."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_drafts-create", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("drafts-delete", + Some(r##"Immediately and permanently deletes the specified draft. Does not simply trash it."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_drafts-delete", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the draft to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("drafts-get", + Some(r##"Gets the specified draft."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_drafts-get", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the draft to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("drafts-list", + Some(r##"Lists the drafts in the user's mailbox."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_drafts-list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("drafts-send", + Some(r##"Sends the specified, existing draft to the recipients in the To, Cc, and Bcc headers."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_drafts-send", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("drafts-update", + Some(r##"Replaces a draft's content."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_drafts-update", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the draft to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-profile", + Some(r##"Gets the current user's Gmail profile."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_get-profile", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("history-list", + Some(r##"Lists the history of all changes to the given mailbox. History results are returned in chronological order (increasing historyId)."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_history-list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("labels-create", + Some(r##"Creates a new label."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_labels-create", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("labels-delete", + Some(r##"Immediately and permanently deletes the specified label and removes it from any messages and threads that it is applied to."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_labels-delete", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the label to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("labels-get", + Some(r##"Gets the specified label."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_labels-get", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the label to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("labels-list", + Some(r##"Lists all labels in the user's mailbox."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_labels-list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("labels-patch", + Some(r##"Updates the specified label. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_labels-patch", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the label to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("labels-update", + Some(r##"Updates the specified label."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_labels-update", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the label to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("messages-attachments-get", + Some(r##"Gets the specified message attachment."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_messages-attachments-get", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"message-id"##), + None, + Some(r##"The ID of the message containing the attachment."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the attachment."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("messages-delete", + Some(r##"Immediately and permanently deletes the specified message. This operation cannot be undone. Prefer messages.trash instead."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_messages-delete", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the message to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("messages-get", + Some(r##"Gets the specified message."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_messages-get", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the message to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("messages-import", + Some(r##"Imports a message into only this user's mailbox, with standard email delivery scanning and classification similar to receiving via SMTP. Does not send a message."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_messages-import", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("messages-insert", + Some(r##"Directly inserts a message into only this user's mailbox similar to IMAP APPEND, bypassing most scanning and classification. Does not send a message."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_messages-insert", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("messages-list", + Some(r##"Lists the messages in the user's mailbox."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_messages-list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("messages-modify", + Some(r##"Modifies the labels on the specified message."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_messages-modify", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the message to modify."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("messages-send", + Some(r##"Sends the specified message to the recipients in the To, Cc, and Bcc headers."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_messages-send", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("messages-trash", + Some(r##"Moves the specified message to the trash."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_messages-trash", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the message to Trash."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("messages-untrash", + Some(r##"Removes the specified message from the trash."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_messages-untrash", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the message to remove from Trash."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("threads-delete", + Some(r##"Immediately and permanently deletes the specified thread. This operation cannot be undone. Prefer threads.trash instead."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_threads-delete", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"ID of the Thread to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("threads-get", + Some(r##"Gets the specified thread."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_threads-get", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the thread to retrieve."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("threads-list", + Some(r##"Lists the threads in the user's mailbox."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_threads-list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("threads-modify", + Some(r##"Modifies the labels applied to the thread. This applies to all messages in the thread."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_threads-modify", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the thread to modify."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("threads-trash", + Some(r##"Moves the specified thread to the trash."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_threads-trash", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the thread to Trash."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("threads-untrash", + Some(r##"Removes the specified thread from the trash."##), + "Details at http://byron.github.io/google-apis-rs/google_gmail1_cli/users_threads-untrash", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The user's email address. The special value me can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the thread to remove from Trash."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("gmail1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150303") + .about("The Gmail REST API.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_gmail1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + if arg_name_str == "mode" { + arg = arg.number_of_values(2); + arg = arg.value_names(&upload_value_names); + + scmd = scmd.arg(Arg::with_name("mime") + .short("m") + .requires("mode") + .required(false) + .help("The file's mime time, like 'application/octet-stream'") + .takes_value(true)); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/gmail1/Cargo.toml b/gen/gmail1/Cargo.toml index d932b5f9e7..eb081e41e9 100644 --- a/gen/gmail1/Cargo.toml +++ b/gen/gmail1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-gmail1" -version = "0.1.6+20150303" +version = "0.1.7+20150303" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with gmail (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/gmail1" @@ -15,9 +15,10 @@ keywords = ["gmail", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/gmail1/README.md b/gen/gmail1/README.md index 4e43891c1c..5100a159a7 100644 --- a/gen/gmail1/README.md +++ b/gen/gmail1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-gmail1` library allows access to all features of the *Google gmail* service. -This documentation was generated from *gmail* crate version *0.1.6+20150303*, where *20150303* is the exact revision of the *gmail:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *gmail* crate version *0.1.7+20150303*, where *20150303* is the exact revision of the *gmail:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *gmail* *v1* API can be found at the [official documentation site](https://developers.google.com/gmail/api/). @@ -184,7 +184,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_gmail1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_gmail1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/gmail1/src/cmn.rs b/gen/gmail1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/gmail1/src/cmn.rs +++ b/gen/gmail1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/gmail1/src/lib.rs b/gen/gmail1/src/lib.rs index 716ddd49cb..91ef79a9fc 100644 --- a/gen/gmail1/src/lib.rs +++ b/gen/gmail1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *gmail* crate version *0.1.6+20150303*, where *20150303* is the exact revision of the *gmail:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *gmail* crate version *0.1.7+20150303*, where *20150303* is the exact revision of the *gmail:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *gmail* *v1* API can be found at the //! [official documentation site](https://developers.google.com/gmail/api/). @@ -185,7 +185,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -194,7 +194,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -210,6 +209,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -357,7 +357,7 @@ impl<'a, C, A> Gmail<C, A> Gmail { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -366,7 +366,7 @@ impl<'a, C, A> Gmail<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1571,6 +1571,7 @@ impl<'a, C, A> UserMessageImportCall<'a, C, A> where C: BorrowMut<hyper::Client> /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, Message)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1646,11 +1647,20 @@ impl<'a, C, A> UserMessageImportCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1705,7 +1715,7 @@ impl<'a, C, A> UserMessageImportCall<'a, C, A> where C: BorrowMut<hyper::Client> _ => (&mut request_value_reader as &mut io::Read, ContentType(json_mime_type.clone())), }; let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(content_type) @@ -1755,7 +1765,7 @@ impl<'a, C, A> UserMessageImportCall<'a, C, A> where C: BorrowMut<hyper::Client> let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -1783,6 +1793,7 @@ impl<'a, C, A> UserMessageImportCall<'a, C, A> where C: BorrowMut<hyper::Client> Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -2056,7 +2067,7 @@ impl<'a, C, A> UserHistoryListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2078,7 +2089,7 @@ impl<'a, C, A> UserHistoryListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2277,6 +2288,7 @@ impl<'a, C, A> UserDraftCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, Draft)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2340,11 +2352,20 @@ impl<'a, C, A> UserDraftCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2399,7 +2420,7 @@ impl<'a, C, A> UserDraftCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, _ => (&mut request_value_reader as &mut io::Read, ContentType(json_mime_type.clone())), }; let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(content_type) @@ -2449,7 +2470,7 @@ impl<'a, C, A> UserDraftCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -2477,6 +2498,7 @@ impl<'a, C, A> UserDraftCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -2654,6 +2676,7 @@ impl<'a, C, A> UserLabelCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Label)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2709,11 +2732,20 @@ impl<'a, C, A> UserLabelCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2736,7 +2768,7 @@ impl<'a, C, A> UserLabelCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2966,7 +2998,7 @@ impl<'a, C, A> UserLabelDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2988,7 +3020,7 @@ impl<'a, C, A> UserLabelDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3207,7 +3239,7 @@ impl<'a, C, A> UserLabelGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3229,7 +3261,7 @@ impl<'a, C, A> UserLabelGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3458,7 +3490,7 @@ impl<'a, C, A> UserMessageTrashCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3480,7 +3512,7 @@ impl<'a, C, A> UserMessageTrashCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3661,6 +3693,7 @@ impl<'a, C, A> UserDraftSendCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, Message)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3724,11 +3757,20 @@ impl<'a, C, A> UserDraftSendCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3783,7 +3825,7 @@ impl<'a, C, A> UserDraftSendCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: _ => (&mut request_value_reader as &mut io::Read, ContentType(json_mime_type.clone())), }; let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(content_type) @@ -3833,7 +3875,7 @@ impl<'a, C, A> UserDraftSendCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -3861,6 +3903,7 @@ impl<'a, C, A> UserDraftSendCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -4088,7 +4131,7 @@ impl<'a, C, A> UserMessageUntrashCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4110,7 +4153,7 @@ impl<'a, C, A> UserMessageUntrashCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4337,7 +4380,7 @@ impl<'a, C, A> UserLabelListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4359,7 +4402,7 @@ impl<'a, C, A> UserLabelListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4577,7 +4620,7 @@ impl<'a, C, A> UserMessageDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4599,7 +4642,7 @@ impl<'a, C, A> UserMessageDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4771,6 +4814,7 @@ impl<'a, C, A> UserDraftUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, Draft)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4835,11 +4879,20 @@ impl<'a, C, A> UserDraftUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4894,7 +4947,7 @@ impl<'a, C, A> UserDraftUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, _ => (&mut request_value_reader as &mut io::Read, ContentType(json_mime_type.clone())), }; let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(content_type) @@ -4944,7 +4997,7 @@ impl<'a, C, A> UserDraftUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -4972,6 +5025,7 @@ impl<'a, C, A> UserDraftUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -5214,7 +5268,7 @@ impl<'a, C, A> UserDraftGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5236,7 +5290,7 @@ impl<'a, C, A> UserDraftGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5423,6 +5477,7 @@ impl<'a, C, A> UserLabelUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Label)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5479,11 +5534,20 @@ impl<'a, C, A> UserLabelUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5506,7 +5570,7 @@ impl<'a, C, A> UserLabelUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5747,7 +5811,7 @@ impl<'a, C, A> UserThreadUntrashCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5769,7 +5833,7 @@ impl<'a, C, A> UserThreadUntrashCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5949,6 +6013,7 @@ impl<'a, C, A> UserLabelPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Label)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6005,11 +6070,20 @@ impl<'a, C, A> UserLabelPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6032,7 +6106,7 @@ impl<'a, C, A> UserLabelPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6272,7 +6346,7 @@ impl<'a, C, A> UserDraftDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6294,7 +6368,7 @@ impl<'a, C, A> UserDraftDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6540,7 +6614,7 @@ impl<'a, C, A> UserThreadListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6562,7 +6636,7 @@ impl<'a, C, A> UserThreadListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6768,6 +6842,7 @@ impl<'a, C, A> UserThreadModifyCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Thread)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6824,11 +6899,20 @@ impl<'a, C, A> UserThreadModifyCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6851,7 +6935,7 @@ impl<'a, C, A> UserThreadModifyCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7091,7 +7175,7 @@ impl<'a, C, A> UserThreadDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7113,7 +7197,7 @@ impl<'a, C, A> UserThreadDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7334,7 +7418,7 @@ impl<'a, C, A> UserMessageAttachmentGetCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7356,7 +7440,7 @@ impl<'a, C, A> UserMessageAttachmentGetCall<'a, C, A> where C: BorrowMut<hyper:: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7546,6 +7630,7 @@ impl<'a, C, A> UserMessageModifyCall<'a, C, A> where C: BorrowMut<hyper::Client> /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Message)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7602,11 +7687,20 @@ impl<'a, C, A> UserMessageModifyCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7629,7 +7723,7 @@ impl<'a, C, A> UserMessageModifyCall<'a, C, A> where C: BorrowMut<hyper::Client> request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7870,7 +7964,7 @@ impl<'a, C, A> UserThreadTrashCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7892,7 +7986,7 @@ impl<'a, C, A> UserThreadTrashCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8129,7 +8223,7 @@ impl<'a, C, A> UserDraftListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8151,7 +8245,7 @@ impl<'a, C, A> UserDraftListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8336,6 +8430,7 @@ impl<'a, C, A> UserMessageSendCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, Message)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8399,11 +8494,20 @@ impl<'a, C, A> UserMessageSendCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8458,7 +8562,7 @@ impl<'a, C, A> UserMessageSendCall<'a, C, A> where C: BorrowMut<hyper::Client>, _ => (&mut request_value_reader as &mut io::Read, ContentType(json_mime_type.clone())), }; let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(content_type) @@ -8508,7 +8612,7 @@ impl<'a, C, A> UserMessageSendCall<'a, C, A> where C: BorrowMut<hyper::Client>, let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -8536,6 +8640,7 @@ impl<'a, C, A> UserMessageSendCall<'a, C, A> where C: BorrowMut<hyper::Client>, Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -8777,7 +8882,7 @@ impl<'a, C, A> UserMessageGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8799,7 +8904,7 @@ impl<'a, C, A> UserMessageGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9070,7 +9175,7 @@ impl<'a, C, A> UserMessageListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9092,7 +9197,7 @@ impl<'a, C, A> UserMessageListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9345,7 +9450,7 @@ impl<'a, C, A> UserGetProfileCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9367,7 +9472,7 @@ impl<'a, C, A> UserGetProfileCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9600,7 +9705,7 @@ impl<'a, C, A> UserThreadGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9622,7 +9727,7 @@ impl<'a, C, A> UserThreadGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9822,6 +9927,7 @@ impl<'a, C, A> UserMessageInsertCall<'a, C, A> where C: BorrowMut<hyper::Client> /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, Message)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9891,11 +9997,20 @@ impl<'a, C, A> UserMessageInsertCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9950,7 +10065,7 @@ impl<'a, C, A> UserMessageInsertCall<'a, C, A> where C: BorrowMut<hyper::Client> _ => (&mut request_value_reader as &mut io::Read, ContentType(json_mime_type.clone())), }; let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(content_type) @@ -10000,7 +10115,7 @@ impl<'a, C, A> UserMessageInsertCall<'a, C, A> where C: BorrowMut<hyper::Client> let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -10028,6 +10143,7 @@ impl<'a, C, A> UserMessageInsertCall<'a, C, A> where C: BorrowMut<hyper::Client> Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } diff --git a/gen/groupsmigration1-cli/Cargo.toml b/gen/groupsmigration1-cli/Cargo.toml index 1f376ea09b..22449fa31a 100644 --- a/gen/groupsmigration1-cli/Cargo.toml +++ b/gen/groupsmigration1-cli/Cargo.toml @@ -17,13 +17,14 @@ keywords = ["groupsmigration", "google", "cli"] name = "groupsmigration1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -clap = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-groupsmigration1] path = "../groupsmigration1" diff --git a/gen/groupsmigration1-cli/README.md b/gen/groupsmigration1-cli/README.md index 2f3b186746..8ff231a100 100644 --- a/gen/groupsmigration1-cli/README.md +++ b/gen/groupsmigration1-cli/README.md @@ -23,9 +23,6 @@ groupsmigration1 [options] insert <group-id> (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] groupsmigration1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_groupsmigration1_cli - Configuration: [--scope <url>]... Specify the authentication a method should be executed in. Each scope diff --git a/gen/groupsmigration1-cli/src/cmn.rs b/gen/groupsmigration1-cli/src/cmn.rs index f784b283db..3335e7b6bd 100644 --- a/gen/groupsmigration1-cli/src/cmn.rs +++ b/gen/groupsmigration1-cli/src/cmn.rs @@ -4,6 +4,7 @@ use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; use serde::json; use mime::Mime; use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -18,14 +19,54 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + pub enum CallType { Upload(UploadProtocol), Standard, } -pub enum UploadProtocol { - Simple, - Resumable, +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } } impl AsRef<str> for UploadProtocol { @@ -46,18 +87,6 @@ impl AsRef<str> for CallType { } } -impl FromStr for UploadProtocol { - type Err = String; - - fn from_str(s: &str) -> Result<UploadProtocol, String> { - match s { - "simple" => Ok(UploadProtocol::Simple), - "resumable" => Ok(UploadProtocol::Resumable), - _ => Err(format!("Protocol '{}' is unknown", s)), - } - } -} - #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -129,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -153,7 +225,7 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } -pub fn protocol_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { CallType::Upload( match UploadProtocol::from_str(name) { Ok(up) => up, @@ -282,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -304,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -327,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -338,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -347,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -363,7 +448,7 @@ impl fmt::Display for FieldError { pub enum CLIError { Configuration(ConfigurationError), ParseError(&'static str, &'static str, String, String), - UnknownParameter(String), + UnknownParameter(String, Vec<&'static str>), InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), @@ -379,18 +464,24 @@ impl fmt::Display for CLIError { CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) - => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}", proto_name, valid_names.connect(", ")), + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, - CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command"), - CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command", cmd), + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } diff --git a/gen/groupsmigration1-cli/src/main.rs b/gen/groupsmigration1-cli/src/main.rs index 4b6d3c7cda..bb01653c02 100644 --- a/gen/groupsmigration1-cli/src/main.rs +++ b/gen/groupsmigration1-cli/src/main.rs @@ -4,12 +4,14 @@ #![feature(plugin, exit_status)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] +#[macro_use] extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_groupsmigration1 as api; use std::env; @@ -20,7 +22,7 @@ mod cmn; use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, - protocol_from_str}; + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; @@ -37,6 +39,8 @@ enum DoitError { struct Engine<'n, 'a> { opt: ArgMatches<'n, 'a>, hub: api::GroupsMigration<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } @@ -47,26 +51,25 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let vals = opt.values_of("mode").unwrap(); - let protocol = protocol_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); let mut input_file = input_file_from_opts(vals[1], err); let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { @@ -87,7 +90,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -165,6 +170,13 @@ impl<'n, 'a> Engine<'n, 'a> { let engine = Engine { opt: opt, hub: api::GroupsMigration::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { @@ -186,29 +198,31 @@ fn main() { let upload_value_names = ["mode", "file"]; let arg_data = [ ("archive", "methods: 'insert'", vec![ - ("insert", Some("Inserts a new mail into the archive of the Google group."), + ("insert", + Some(r##"Inserts a new mail into the archive of the Google group."##), + "Details at http://byron.github.io/google-apis-rs/google_groupsmigration1_cli/archive_insert", vec![ - (Some("group-id"), + (Some(r##"group-id"##), None, - Some("The group ID"), + Some(r##"The group ID"##), Some(true), Some(false)), - (Some("mode"), - Some("u"), - Some("Specify the upload protocol (simple|resumable) and the file to upload"), + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), @@ -245,11 +259,12 @@ fn main() { for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { let mut mcmd = SubCommand::new(main_command_name).about(about); - for &(sub_command_name, ref desc, ref args) in subcommands { + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { let mut scmd = SubCommand::new(sub_command_name); if let &Some(desc) = desc { scmd = scmd.about(desc); } + scmd = scmd.after_help(url_info); for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { let arg_name_str = diff --git a/gen/groupsmigration1/Cargo.toml b/gen/groupsmigration1/Cargo.toml index 72e4b27d5a..362f5964b1 100644 --- a/gen/groupsmigration1/Cargo.toml +++ b/gen/groupsmigration1/Cargo.toml @@ -15,9 +15,10 @@ keywords = ["groupsmigration", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/groupsmigration1/src/cmn.rs b/gen/groupsmigration1/src/cmn.rs index 92b10c0eb1..908bef39dc 100644 --- a/gen/groupsmigration1/src/cmn.rs +++ b/gen/groupsmigration1/src/cmn.rs @@ -43,7 +43,7 @@ pub trait RequestValue {} /// This might be a bug within the google API schema. pub trait UnusedType {} -/// Identifies types which are only used as part of other types, which +/// Identifies types which are only used as part of other types, which /// usually are carrying the `Resource` trait. pub trait Part {} @@ -78,7 +78,7 @@ pub struct ErrorResponse { pub struct ServerError { errors: Vec<ServerMessage>, code: u16, - message: String, + message: String, } #[derive(Deserialize, Serialize, Debug)] @@ -120,7 +120,7 @@ impl hyper::net::NetworkStream for DummyNetworkStream { /// A trait specifying functionality to help controlling any request performed by the API. /// The trait has a conservative default implementation. /// -/// It contains methods to deal with all common issues, as well with the ones related to +/// It contains methods to deal with all common issues, as well with the ones related to /// uploading media pub trait Delegate { @@ -128,21 +128,21 @@ pub trait Delegate { /// information if he is interesting in knowing more context when further calls to it /// are made. /// The matching `finished()` call will always be made, no matter whether or not the API - /// request was successful. That way, the delegate may easily maintain a clean state + /// request was successful. That way, the delegate may easily maintain a clean state /// between various API calls. fn begin(&mut self, MethodInfo) {} /// Called whenever there is an [HttpError](http://hyperium.github.io/hyper/hyper/error/enum.HttpError.html), usually if there are network problems. - /// + /// /// If you choose to retry after a duration, the duration should be chosen using the /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } - /// Called whenever there is the need for your applications API key after + /// Called whenever there is the need for your applications API key after /// the official authenticator implementation didn't provide one, for some reason. /// If this method returns None as well, the underlying operation will fail fn api_key(&mut self) -> Option<String> { @@ -171,7 +171,7 @@ pub trait Delegate { } /// Called after we have retrieved a new upload URL for a resumable upload to store it - /// in case we fail or cancel. That way, we can attempt to resume the upload later, + /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. /// It will also be called with None after a successful upload, which allows the delegate /// to forget the URL. That way, we will not attempt to resume an upload that has already @@ -183,7 +183,7 @@ pub trait Delegate { /// Called whenever a server response could not be decoded from json. /// It's for informational purposes only, the caller will return with an error /// accordingly. - /// + /// /// # Arguments /// /// * `json_encoded_value` - The json-encoded value which failed to decode. @@ -194,7 +194,7 @@ pub trait Delegate { } /// Called whenever the http request returns with a non-success status code. - /// This can involve authentication issues, or anything else that very much + /// This can involve authentication issues, or anything else that very much /// depends on the used API method. /// The delegate should check the status, header and decoded json error to decide /// whether to retry or not. In the latter case, the underlying call will fail. @@ -205,7 +205,7 @@ pub trait Delegate { Retry::Abort } - /// Called prior to sending the main request of the given method. It can be used to time + /// Called prior to sending the main request of the given method. It can be used to time /// the call or to print progress information. /// It's also useful as you can be sure that a request will definitely be made. fn pre_request(&mut self) { } @@ -224,14 +224,14 @@ pub trait Delegate { fn cancel_chunk_upload(&mut self, chunk: &ContentRange) -> bool { let _ = chunk; false - } + } /// Called before the API request method returns, in every case. It can be used to clean up /// internal state between calls to the API. /// This call always has a matching call to `begin(...)`. /// /// # Arguments - /// + /// /// * `is_success` - a true value indicates the operation was successful. If false, you should /// discard all values stored during `store_upload_url`. fn finished(&mut self, is_success: bool) { @@ -250,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -293,17 +293,29 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), - Error::Cancelled => + Error::Cancelled => writeln!(f, "Operation cancelled by delegate"), Error::FieldClash(field) => writeln!(f, "The custom parameter '{}' is already provided natively by the CallBuilder.", field), - Error::JsonDecodeError(ref json_str, ref err) + Error::JsonDecodeError(ref json_str, ref err) => writeln!(f, "{}: {}", err, json_str), - Error::Failure(ref response) => + Error::Failure(ref response) => writeln!(f, "Http status indicates failure: {:?}", response), } } @@ -398,8 +410,8 @@ impl<'a> MultiPartReader<'a> { impl<'a> Read for MultiPartReader<'a> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - match (self.raw_parts.len(), - self.current_part.is_none(), + match (self.raw_parts.len(), + self.current_part.is_none(), self.last_part_boundary.is_none()) { (_, _, false) => { let br = self.last_part_boundary.as_mut().unwrap().read(buf).unwrap_or(0); @@ -412,7 +424,7 @@ impl<'a> Read for MultiPartReader<'a> { (n, true, _) if n > 0 => { let (headers, reader) = self.raw_parts.remove(0); let mut c = Cursor::new(Vec::<u8>::new()); - write!(&mut c, "{}--{}{}{}{}", LINE_ENDING, BOUNDARY, LINE_ENDING, + write!(&mut c, "{}--{}{}{}{}", LINE_ENDING, BOUNDARY, LINE_ENDING, headers, LINE_ENDING).unwrap(); c.seek(SeekFrom::Start(0)).unwrap(); self.current_part = Some((c, reader)); @@ -426,12 +438,12 @@ impl<'a> Read for MultiPartReader<'a> { let b = c.read(buf).unwrap_or(0); (b, reader.read(&mut buf[b..])) }; - + match rr { Ok(bytes_read) => { if hb < buf.len() && bytes_read == 0 { if self.is_last_part() { - // before clearing the last part, we will add the boundary that + // before clearing the last part, we will add the boundary that // will be written last self.last_part_boundary = Some(Cursor::new( format!("{}--{}--", LINE_ENDING, BOUNDARY).into_bytes())) @@ -589,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -625,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { @@ -669,7 +681,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> if !res.status.is_success() { let mut json_err = String::new(); res.read_to_string(&mut json_err).unwrap(); - if let Retry::After(d) = self.delegate.http_failure(&res, + if let Retry::After(d) = self.delegate.http_failure(&res, serde::json::from_str(&json_err).ok(), serde::json::from_str(&json_err).ok()) { sleep_ms(d.num_milliseconds() as u32); @@ -688,4 +700,4 @@ impl<'a, A> ResumableUploadHelper<'a, A> } } } -} +} \ No newline at end of file diff --git a/gen/groupsmigration1/src/lib.rs b/gen/groupsmigration1/src/lib.rs index 38b0d5735c..68df951c23 100644 --- a/gen/groupsmigration1/src/lib.rs +++ b/gen/groupsmigration1/src/lib.rs @@ -3,30 +3,30 @@ // DO NOT EDIT ! //! This documentation was generated from *Groups Migration* crate version *0.1.7+20140416*, where *20140416* is the exact revision of the *groupsmigration:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. -//! +//! //! Everything else about the *Groups Migration* *v1* API can be found at the //! [official documentation site](https://developers.google.com/google-apps/groups-migration/). //! The original source code is [on github](https://github.com/Byron/google-apis-rs/tree/master/gen/groupsmigration1). //! # Features -//! -//! Handle the following *Resources* with ease from the central [hub](struct.GroupsMigration.html) ... -//! +//! +//! Handle the following *Resources* with ease from the central [hub](struct.GroupsMigration.html) ... +//! //! * archive //! * [*insert*](struct.ArchiveInsertCall.html) -//! -//! +//! +//! //! Upload supported by ... -//! +//! //! * [*insert archive*](struct.ArchiveInsertCall.html) -//! -//! -//! +//! +//! +//! //! Not what you are looking for ? Find all other Google APIs in their Rust [documentation index](../index.html). -//! +//! //! # Structure of this Library -//! +//! //! The API is structured into the following primary items: -//! +//! //! * **[Hub](struct.GroupsMigration.html)** //! * a central object to maintain state and allow accessing all *Activities* //! * creates [*Method Builders*](trait.MethodsBuilder.html) which in turn @@ -39,39 +39,39 @@ //! * never directly used in *Activities* //! * **[Activities](trait.CallBuilder.html)** //! * operations to apply to *Resources* -//! +//! //! All *structures* are marked with applicable traits to further categorize them and ease browsing. -//! +//! //! Generally speaking, you can invoke *Activities* like this: -//! +//! //! ```Rust,ignore //! let r = hub.resource().activity(...).doit() //! ``` -//! +//! //! Or specifically ... -//! +//! //! ```ignore //! let r = hub.archive().insert(...).doit() //! ``` -//! -//! The `resource()` and `activity(...)` calls create [builders][builder-pattern]. The second one dealing with `Activities` -//! supports various methods to configure the impending operation (not shown here). It is made such that all required arguments have to be +//! +//! The `resource()` and `activity(...)` calls create [builders][builder-pattern]. The second one dealing with `Activities` +//! supports various methods to configure the impending operation (not shown here). It is made such that all required arguments have to be //! specified right away (i.e. `(...)`), whereas all optional ones can be [build up][builder-pattern] as desired. //! The `doit()` method performs the actual communication with the server and returns the respective result. -//! +//! //! # Usage -//! +//! //! ## Setting up your Project -//! +//! //! To use this library, you would put the following lines into your `Cargo.toml` file: -//! +//! //! ```toml //! [dependencies] //! google-groupsmigration1 = "*" //! ``` -//! +//! //! ## A complete example -//! +//! //! ```test_harness,no_run //! extern crate hyper; //! extern crate yup_oauth2 as oauth2; @@ -82,13 +82,13 @@ //! use std::default::Default; //! use oauth2::{Authenticator, DefaultAuthenticatorDelegate, ApplicationSecret, MemoryStorage}; //! use groupsmigration1::GroupsMigration; -//! -//! // Get an ApplicationSecret instance by some means. It contains the `client_id` and +//! +//! // Get an ApplicationSecret instance by some means. It contains the `client_id` and //! // `client_secret`, among other things. //! let secret: ApplicationSecret = Default::default(); -//! // Instantiate the authenticator. It will choose a suitable authentication flow for you, +//! // Instantiate the authenticator. It will choose a suitable authentication flow for you, //! // unless you replace `None` with the desired Flow. -//! // Provide your own `AuthenticatorDelegate` to adjust the way it operates and get feedback about +//! // Provide your own `AuthenticatorDelegate` to adjust the way it operates and get feedback about //! // what's going on. You probably want to bring in your own `TokenStorage` to persist tokens and //! // retrieve them from storage. //! let auth = Authenticator::new(&secret, DefaultAuthenticatorDelegate, @@ -100,7 +100,7 @@ //! // Values shown here are possibly random and not representative ! //! let result = hub.archive().insert("groupId") //! .upload(fs::File::open("file.ext").unwrap(), "application/octet-stream".parse().unwrap()); -//! +//! //! match result { //! Err(e) => match e { //! // The Error enum provides details about what exactly happened. @@ -120,61 +120,61 @@ //! # } //! ``` //! ## Handling Errors -//! -//! All errors produced by the system are provided either as [Result](enum.Result.html) enumeration as return value of -//! the doit() methods, or handed as possibly intermediate results to either the +//! +//! All errors produced by the system are provided either as [Result](enum.Result.html) enumeration as return value of +//! the doit() methods, or handed as possibly intermediate results to either the //! [Hub Delegate](trait.Delegate.html), or the [Authenticator Delegate](../yup-oauth2/trait.AuthenticatorDelegate.html). -//! -//! When delegates handle errors or intermediate values, they may have a chance to instruct the system to retry. This +//! +//! When delegates handle errors or intermediate values, they may have a chance to instruct the system to retry. This //! makes the system potentially resilient to all kinds of errors. -//! +//! //! ## Uploads and Downloads //! If a method supports downloads, the response body, which is part of the [Result](enum.Result.html), should be //! read by you to obtain the media. //! If such a method also supports a [Response Result](trait.ResponseResult.html), it will return that by default. //! You can see it as meta-data for the actual media. To trigger a media download, you will have to set up the builder by making //! this call: `.param("alt", "media")`. -//! -//! Methods supporting uploads can do so using up to 2 different protocols: -//! *simple* and *resumable*. The distinctiveness of each is represented by customized +//! +//! Methods supporting uploads can do so using up to 2 different protocols: +//! *simple* and *resumable*. The distinctiveness of each is represented by customized //! `doit(...)` methods, which are then named `upload(...)` and `upload_resumable(...)` respectively. -//! +//! //! ## Customization and Callbacks -//! -//! You may alter the way an `doit()` method is called by providing a [delegate](trait.Delegate.html) to the -//! [Method Builder](trait.CallBuilder.html) before making the final `doit()` call. -//! Respective methods will be called to provide progress information, as well as determine whether the system should +//! +//! You may alter the way an `doit()` method is called by providing a [delegate](trait.Delegate.html) to the +//! [Method Builder](trait.CallBuilder.html) before making the final `doit()` call. +//! Respective methods will be called to provide progress information, as well as determine whether the system should //! retry on failure. -//! +//! //! The [delegate trait](trait.Delegate.html) is default-implemented, allowing you to customize it with minimal effort. -//! +//! //! ## Optional Parts in Server-Requests -//! -//! All structures provided by this library are made to be [enocodable](trait.RequestValue.html) and -//! [decodable](trait.ResponseResult.html) via *json*. Optionals are used to indicate that partial requests are responses +//! +//! All structures provided by this library are made to be [enocodable](trait.RequestValue.html) and +//! [decodable](trait.ResponseResult.html) via *json*. Optionals are used to indicate that partial requests are responses //! are valid. -//! Most optionals are are considered [Parts](trait.Part.html) which are identifiable by name, which will be sent to +//! Most optionals are are considered [Parts](trait.Part.html) which are identifiable by name, which will be sent to //! the server to indicate either the set parts of the request or the desired parts in the response. -//! +//! //! ## Builder Arguments -//! +//! //! Using [method builders](trait.CallBuilder.html), you are able to prepare an action call by repeatedly calling it's methods. //! These will always take a single argument, for which the following statements are true. -//! +//! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` //! * [request values](trait.RequestValue.html) are moved -//! +//! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. -//! +//! //! [wiki-pod]: http://en.wikipedia.org/wiki/Plain_old_data_structure //! [builder-pattern]: http://en.wikipedia.org/wiki/Builder_pattern //! [google-go-api]: https://github.com/google/google-api-go-client -//! -//! +//! +//! // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. -// Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any +// Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any // unused imports in fully featured APIs. Same with unused_mut ... . #![allow(unused_imports, unused_mut, dead_code)] // Required for serde annotations @@ -187,6 +187,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -200,10 +201,7 @@ use std::io; use std::fs; use std::thread::sleep_ms; -pub use cmn::{MultiPartReader, ToParts, MethodInfo, Result, Error, - CallBuilder, Hub, ReadSeek, Part, ResponseResult, - RequestValue, NestedType, Delegate, DefaultDelegate, - MethodsBuilder, Resource, ErrorResponse}; +pub use cmn::{MultiPartReader, ToParts, MethodInfo, Result, Error, CallBuilder, Hub, ReadSeek, Part, ResponseResult, RequestValue, NestedType, Delegate, DefaultDelegate, MethodsBuilder, Resource, ErrorResponse}; // ############## @@ -393,7 +391,7 @@ pub struct ArchiveMethods<'a, C, A> impl<'a, C, A> MethodsBuilder for ArchiveMethods<'a, C, A> {} impl<'a, C, A> ArchiveMethods<'a, C, A> { - + /// Create a builder to help you perform the following task: /// /// Inserts a new mail into the archive of the Google group. @@ -467,16 +465,10 @@ impl<'a, C, A> ArchiveInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. - fn doit<RS>(mut self, - mut reader: RS, - reader_mime_type: mime::Mime, - protocol: &'static str) - -> Result<(hyper::client::Response, Groups)> - where RS: ReadSeek - { + fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, Groups)> + where RS: ReadSeek { use std::io::{Read, Seek}; - use hyper::header::{ContentType, ContentLength, Authorization, - UserAgent, Location}; + use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; let mut dlg: &mut Delegate = match self._delegate { Some(d) => d, @@ -498,7 +490,7 @@ impl<'a, C, A> ArchiveInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: params.push(("alt", "json".to_string())); - let (mut url, upload_type) = + let (mut url, upload_type) = if protocol == "simple" { ("https://www.googleapis.com/upload/groups/v1/groups/{groupId}/archive".to_string(), "multipart") } else if protocol == "resumable" { @@ -535,10 +527,10 @@ impl<'a, C, A> ArchiveInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: params.remove(index); } } - + if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -694,12 +686,8 @@ impl<'a, C, A> ArchiveInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// * *max size*: 16MB /// * *multipart*: yes /// * *valid mime types*: 'message/rfc822' - pub fn upload<RS>(self, - stream: RS, - mime_type: mime::Mime) - -> Result<(hyper::client::Response, Groups)> - where RS: ReadSeek - { + pub fn upload<RS>(self, stream: RS, mime_type: mime::Mime) -> Result<(hyper::client::Response, Groups)> + where RS: ReadSeek { self.doit(stream, mime_type, "simple") } /// Upload media in a resumable fashion. @@ -714,12 +702,8 @@ impl<'a, C, A> ArchiveInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// * *max size*: 16MB /// * *multipart*: yes /// * *valid mime types*: 'message/rfc822' - pub fn upload_resumable<RS>(self, - resumeable_stream: RS, - mime_type: mime::Mime) - -> Result<(hyper::client::Response, Groups)> - where RS: ReadSeek - { + pub fn upload_resumable<RS>(self, resumeable_stream: RS, mime_type: mime::Mime) -> Result<(hyper::client::Response, Groups)> + where RS: ReadSeek { self.doit(resumeable_stream, mime_type, "resumable") } @@ -761,8 +745,7 @@ impl<'a, C, A> ArchiveInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// * *fields* (query-string) - Selector specifying which fields to include in a partial response. /// * *alt* (query-string) - Data format for the response. pub fn param<T>(mut self, name: T, value: T) -> ArchiveInsertCall<'a, C, A> - where T: AsRef<str> - { + where T: AsRef<str> { self._additional_params.insert(name.as_ref().to_string(), value.as_ref().to_string()); self } @@ -778,10 +761,11 @@ impl<'a, C, A> ArchiveInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Usually there is more than one suitable scope to authorize an operation, some of which may /// encompass more rights than others. For example, for listing resources, a *read-only* scope will be /// sufficient, a read-write scope will do as well. - pub fn add_scope<T>(mut self, scope: T) -> ArchiveInsertCall<'a, C, A> - where T: AsRef<str> - { + pub fn add_scope<T>(mut self, scope: T) -> ArchiveInsertCall<'a, C, A> + where T: AsRef<str> { self._scopes.insert(scope.as_ref().to_string(), ()); self } } + + diff --git a/gen/groupssettings1-cli/Cargo.toml b/gen/groupssettings1-cli/Cargo.toml index be66f4952b..506cec9785 100644 --- a/gen/groupssettings1-cli/Cargo.toml +++ b/gen/groupssettings1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-groupssettings1-cli" -version = "0.1.0+20140428" +version = "0.2.0+20140428" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with groupssettings (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/groupssettings1-cli" @@ -17,15 +17,14 @@ keywords = ["groupssettings", "google", "cli"] name = "groupssettings1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-groupssettings1] path = "../groupssettings1" diff --git a/gen/groupssettings1-cli/README.md b/gen/groupssettings1-cli/README.md index d748a8404f..4d6c9cee9a 100644 --- a/gen/groupssettings1-cli/README.md +++ b/gen/groupssettings1-cli/README.md @@ -10,23 +10,25 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *groupssettings* API can be found at the +[official documentation site](https://developers.google.com/google-apps/groups-settings/get_started). + # Usage -This documentation was generated from the *groupssettings* API at revision *20140428*. The CLI is at version *0.1.0*. +This documentation was generated from the *groupssettings* API at revision *20140428*. The CLI is at version *0.2.0*. ```bash - groupssettings1 [options] groups get <group-unique-id> [-p <v>...] [-o <out>] - groupssettings1 [options] groups patch <group-unique-id> -r <kv>... [-p <v>...] [-o <out>] - groupssettings1 [options] groups update <group-unique-id> -r <kv>... [-p <v>...] [-o <out>] +groupssettings1 [options] + groups + get <group-unique-id> [-p <v>]... [-o <out>] + patch <group-unique-id> (-r <kv>)... [-p <v>]... [-o <out>] + update <group-unique-id> (-r <kv>)... [-p <v>]... [-o <out>] groupssettings1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_groupssettings1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/groupssettings1-cli/mkdocs.yml b/gen/groupssettings1-cli/mkdocs.yml index 10738917fd..4796c5507f 100644 --- a/gen/groupssettings1-cli/mkdocs.yml +++ b/gen/groupssettings1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: groupssettings v0.1.0+20140428 +site_name: groupssettings v0.2.0+20140428 site_url: http://byron.github.io/google-apis-rs/google-groupssettings1-cli site_description: Write integrating applications with bcore diff --git a/gen/groupssettings1-cli/src/cmn.rs b/gen/groupssettings1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/groupssettings1-cli/src/cmn.rs +++ b/gen/groupssettings1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/groupssettings1-cli/src/main.rs b/gen/groupssettings1-cli/src/main.rs index 398ae8c799..ee937fbb6d 100644 --- a/gen/groupssettings1-cli/src/main.rs +++ b/gen/groupssettings1-cli/src/main.rs @@ -2,117 +2,105 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_groupssettings1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - groupssettings1 [options] groups get <group-unique-id> [-p <v>...] [-o <out>] - groupssettings1 [options] groups patch <group-unique-id> -r <kv>... [-p <v>...] [-o <out>] - groupssettings1 [options] groups update <group-unique-id> -r <kv>... [-p <v>...] [-o <out>] - groupssettings1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_groupssettings1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Groupssettings<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _groups_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.groups().get(&self.opt.arg_group_unique_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _groups_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.groups().get(opt.value_of("group-unique-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _groups_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _groups_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Groups::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -212,60 +200,65 @@ impl Engine { request.allow_google_communication = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["allow-external-members", "allow-google-communication", "allow-web-posting", "archive-only", "custom-reply-to", "default-message-deny-notification-text", "description", "email", "include-in-global-address-list", "is-archived", "kind", "max-message-bytes", "members-can-post-as-the-group", "message-display-font", "message-moderation-level", "name", "primary-language", "reply-to", "send-message-deny-notification", "show-in-group-directory", "spam-moderation-level", "who-can-contact-owner", "who-can-invite", "who-can-join", "who-can-leave-group", "who-can-post-message", "who-can-view-group", "who-can-view-membership"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.groups().patch(request, &self.opt.arg_group_unique_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.groups().patch(request, opt.value_of("group-unique-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _groups_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _groups_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Groups::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -365,85 +358,101 @@ impl Engine { request.allow_google_communication = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["allow-external-members", "allow-google-communication", "allow-web-posting", "archive-only", "custom-reply-to", "default-message-deny-notification-text", "description", "email", "include-in-global-address-list", "is-archived", "kind", "max-message-bytes", "members-can-post-as-the-group", "message-display-font", "message-moderation-level", "name", "primary-language", "reply-to", "send-message-deny-notification", "show-in-group-directory", "spam-moderation-level", "who-can-contact-owner", "who-can-invite", "who-can-join", "who-can-leave-group", "who-can-post-message", "who-can-view-group", "who-can-view-membership"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.groups().update(request, &self.opt.arg_group_unique_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.groups().update(request, opt.value_of("group-unique-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_groups { - if self.opt.cmd_get { - call_result = self._groups_get(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._groups_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._groups_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("groups", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._groups_get(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._groups_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._groups_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("groups".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -456,7 +465,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -469,7 +478,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -479,37 +488,204 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Groupssettings::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("groups", "methods: 'get', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets one resource by id."##), + "Details at http://byron.github.io/google-apis-rs/google_groupssettings1_cli/groups_get", + vec![ + (Some(r##"group-unique-id"##), + None, + Some(r##"The resource ID"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an existing resource. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_groupssettings1_cli/groups_patch", + vec![ + (Some(r##"group-unique-id"##), + None, + Some(r##"The resource ID"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing resource."##), + "Details at http://byron.github.io/google-apis-rs/google_groupssettings1_cli/groups_update", + vec![ + (Some(r##"group-unique-id"##), + None, + Some(r##"The resource ID"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("groupssettings1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20140428") + .about("Lets you manage permission levels and related settings of a group.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_groupssettings1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/groupssettings1/Cargo.toml b/gen/groupssettings1/Cargo.toml index 17b57f4a41..d08a1b07aa 100644 --- a/gen/groupssettings1/Cargo.toml +++ b/gen/groupssettings1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-groupssettings1" -version = "0.1.6+20140428" +version = "0.1.7+20140428" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with groupssettings (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/groupssettings1" @@ -15,9 +15,10 @@ keywords = ["groupssettings", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/groupssettings1/README.md b/gen/groupssettings1/README.md index d5e61c3b3b..ce4566f42b 100644 --- a/gen/groupssettings1/README.md +++ b/gen/groupssettings1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-groupssettings1` library allows access to all features of the *Google groupssettings* service. -This documentation was generated from *groupssettings* crate version *0.1.6+20140428*, where *20140428* is the exact revision of the *groupssettings:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *groupssettings* crate version *0.1.7+20140428*, where *20140428* is the exact revision of the *groupssettings:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *groupssettings* *v1* API can be found at the [official documentation site](https://developers.google.com/google-apps/groups-settings/get_started). @@ -165,7 +165,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_groupssettings1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_groupssettings1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/groupssettings1/src/cmn.rs b/gen/groupssettings1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/groupssettings1/src/cmn.rs +++ b/gen/groupssettings1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/groupssettings1/src/lib.rs b/gen/groupssettings1/src/lib.rs index b0c1d568fb..f502693d7f 100644 --- a/gen/groupssettings1/src/lib.rs +++ b/gen/groupssettings1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *groupssettings* crate version *0.1.6+20140428*, where *20140428* is the exact revision of the *groupssettings:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *groupssettings* crate version *0.1.7+20140428*, where *20140428* is the exact revision of the *groupssettings:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *groupssettings* *v1* API can be found at the //! [official documentation site](https://developers.google.com/google-apps/groups-settings/get_started). @@ -166,7 +166,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -175,7 +175,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -191,6 +190,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -313,7 +313,7 @@ impl<'a, C, A> Groupssettings<C, A> Groupssettings { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -322,7 +322,7 @@ impl<'a, C, A> Groupssettings<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -596,6 +596,7 @@ impl<'a, C, A> GroupUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Groups)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -651,11 +652,20 @@ impl<'a, C, A> GroupUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -678,7 +688,7 @@ impl<'a, C, A> GroupUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -859,6 +869,7 @@ impl<'a, C, A> GroupPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Groups)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -914,11 +925,20 @@ impl<'a, C, A> GroupPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -941,7 +961,7 @@ impl<'a, C, A> GroupPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1170,7 +1190,7 @@ impl<'a, C, A> GroupGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1192,7 +1212,7 @@ impl<'a, C, A> GroupGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/identitytoolkit3-cli/Cargo.toml b/gen/identitytoolkit3-cli/Cargo.toml index 7aa5a224bf..816ea68fbd 100644 --- a/gen/identitytoolkit3-cli/Cargo.toml +++ b/gen/identitytoolkit3-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-identitytoolkit3-cli" -version = "0.1.0+20150406" +version = "0.2.0+20150406" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with Identity Toolkit (protocol v3)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/identitytoolkit3-cli" @@ -17,15 +17,14 @@ keywords = ["identitytoolkit", "google", "cli"] name = "identitytoolkit3" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-identitytoolkit3] path = "../identitytoolkit3" diff --git a/gen/identitytoolkit3-cli/README.md b/gen/identitytoolkit3-cli/README.md index 37622e3af7..c811d3cbb4 100644 --- a/gen/identitytoolkit3-cli/README.md +++ b/gen/identitytoolkit3-cli/README.md @@ -10,28 +10,30 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *Identity Toolkit* API can be found at the +[official documentation site](https://developers.google.com/identity-toolkit/v3/). + # Usage -This documentation was generated from the *Identity Toolkit* API at revision *20150406*. The CLI is at version *0.1.0*. +This documentation was generated from the *Identity Toolkit* API at revision *20150406*. The CLI is at version *0.2.0*. ```bash - identitytoolkit3 [options] relyingparty create-auth-uri -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty delete-account -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty download-account -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty get-account-info -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty get-oob-confirmation-code -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty get-public-keys [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty get-recaptcha-param [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty reset-password -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty set-account-info -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty upload-account -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty verify-assertion -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty verify-password -r <kv>... [-p <v>...] [-o <out>] +identitytoolkit3 [options] + relyingparty + create-auth-uri (-r <kv>)... [-p <v>]... [-o <out>] + delete-account (-r <kv>)... [-p <v>]... [-o <out>] + download-account (-r <kv>)... [-p <v>]... [-o <out>] + get-account-info (-r <kv>)... [-p <v>]... [-o <out>] + get-oob-confirmation-code (-r <kv>)... [-p <v>]... [-o <out>] + get-public-keys [-p <v>]... [-o <out>] + get-recaptcha-param [-p <v>]... [-o <out>] + reset-password (-r <kv>)... [-p <v>]... [-o <out>] + set-account-info (-r <kv>)... [-p <v>]... [-o <out>] + upload-account (-r <kv>)... [-p <v>]... [-o <out>] + verify-assertion (-r <kv>)... [-p <v>]... [-o <out>] + verify-password (-r <kv>)... [-p <v>]... [-o <out>] identitytoolkit3 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli/index.html - Configuration: --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/identitytoolkit3-cli/mkdocs.yml b/gen/identitytoolkit3-cli/mkdocs.yml index f3cb0895eb..e130d1f9df 100644 --- a/gen/identitytoolkit3-cli/mkdocs.yml +++ b/gen/identitytoolkit3-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Identity Toolkit v0.1.0+20150406 +site_name: Identity Toolkit v0.2.0+20150406 site_url: http://byron.github.io/google-apis-rs/google-identitytoolkit3-cli site_description: Write integrating applications with bcore diff --git a/gen/identitytoolkit3-cli/src/cmn.rs b/gen/identitytoolkit3-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/identitytoolkit3-cli/src/cmn.rs +++ b/gen/identitytoolkit3-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/identitytoolkit3-cli/src/main.rs b/gen/identitytoolkit3-cli/src/main.rs index d7fde8a5f6..ec31befea7 100644 --- a/gen/identitytoolkit3-cli/src/main.rs +++ b/gen/identitytoolkit3-cli/src/main.rs @@ -2,76 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_identitytoolkit3 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - identitytoolkit3 [options] relyingparty create-auth-uri -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty delete-account -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty download-account -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty get-account-info -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty get-oob-confirmation-code -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty get-public-keys [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty get-recaptcha-param [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty reset-password -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty set-account-info -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty upload-account -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty verify-assertion -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 [options] relyingparty verify-password -r <kv>... [-p <v>...] [-o <out>] - identitytoolkit3 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli/index.html - -Configuration: - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::IdentityToolkit<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _relyingparty_create_auth_uri(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _relyingparty_create_auth_uri(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::IdentitytoolkitRelyingpartyCreateAuthUriRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -117,57 +96,62 @@ impl Engine { request.identifier = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["app-id", "client-id", "context", "continue-uri", "identifier", "oauth-consumer-key", "oauth-scope", "openid-realm", "ota-app", "provider-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.relyingparty().create_auth_uri(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _relyingparty_delete_account(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _relyingparty_delete_account(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::IdentitytoolkitRelyingpartyDeleteAccountRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -186,57 +170,62 @@ impl Engine { request.local_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["local-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.relyingparty().delete_account(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _relyingparty_download_account(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _relyingparty_download_account(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::IdentitytoolkitRelyingpartyDownloadAccountRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -258,57 +247,62 @@ impl Engine { request.max_results = Some(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["max-results", "next-page-token"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.relyingparty().download_account(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _relyingparty_get_account_info(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _relyingparty_get_account_info(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::IdentitytoolkitRelyingpartyGetAccountInfoRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -339,57 +333,62 @@ impl Engine { request.local_id.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["email", "id-token", "local-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.relyingparty().get_account_info(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _relyingparty_get_oob_confirmation_code(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _relyingparty_get_oob_confirmation_code(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Relyingparty::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -429,143 +428,156 @@ impl Engine { request.captcha_resp = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["captcha-resp", "challenge", "email", "id-token", "kind", "new-email", "request-type", "user-ip"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.relyingparty().get_oob_confirmation_code(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _relyingparty_get_public_keys(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _relyingparty_get_public_keys(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.relyingparty().get_public_keys(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _relyingparty_get_recaptcha_param(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _relyingparty_get_recaptcha_param(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.relyingparty().get_recaptcha_param(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _relyingparty_reset_password(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _relyingparty_reset_password(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::IdentitytoolkitRelyingpartyResetPasswordRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -593,57 +605,62 @@ impl Engine { request.email = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["email", "new-password", "old-password", "oob-code"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.relyingparty().reset_password(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _relyingparty_set_account_info(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _relyingparty_set_account_info(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::IdentitytoolkitRelyingpartySetAccountInfoRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -695,57 +712,62 @@ impl Engine { request.email = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["captcha-challenge", "captcha-response", "display-name", "email", "email-verified", "id-token", "local-id", "oob-code", "password", "provider", "upgrade-to-federated-login"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.relyingparty().set_account_info(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _relyingparty_upload_account(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _relyingparty_upload_account(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::IdentitytoolkitRelyingpartyUploadAccountRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -776,57 +798,62 @@ impl Engine { request.rounds = Some(arg_from_str(value.unwrap_or("-0"), err, "rounds", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["hash-algorithm", "memory-cost", "rounds", "salt-separator", "signer-key"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.relyingparty().upload_account(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _relyingparty_verify_assertion(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _relyingparty_verify_assertion(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::IdentitytoolkitRelyingpartyVerifyAssertionRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -854,57 +881,62 @@ impl Engine { request.pending_id_token = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["pending-id-token", "post-body", "request-uri", "return-refresh-token"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.relyingparty().verify_assertion(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _relyingparty_verify_password(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _relyingparty_verify_password(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::IdentitytoolkitRelyingpartyVerifyPasswordRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -935,100 +967,125 @@ impl Engine { request.pending_id_token = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["captcha-challenge", "captcha-response", "email", "password", "pending-id-token"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.relyingparty().verify_password(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_relyingparty { - if self.opt.cmd_create_auth_uri { - call_result = self._relyingparty_create_auth_uri(dry_run, &mut err); - } else if self.opt.cmd_delete_account { - call_result = self._relyingparty_delete_account(dry_run, &mut err); - } else if self.opt.cmd_download_account { - call_result = self._relyingparty_download_account(dry_run, &mut err); - } else if self.opt.cmd_get_account_info { - call_result = self._relyingparty_get_account_info(dry_run, &mut err); - } else if self.opt.cmd_get_oob_confirmation_code { - call_result = self._relyingparty_get_oob_confirmation_code(dry_run, &mut err); - } else if self.opt.cmd_get_public_keys { - call_result = self._relyingparty_get_public_keys(dry_run, &mut err); - } else if self.opt.cmd_get_recaptcha_param { - call_result = self._relyingparty_get_recaptcha_param(dry_run, &mut err); - } else if self.opt.cmd_reset_password { - call_result = self._relyingparty_reset_password(dry_run, &mut err); - } else if self.opt.cmd_set_account_info { - call_result = self._relyingparty_set_account_info(dry_run, &mut err); - } else if self.opt.cmd_upload_account { - call_result = self._relyingparty_upload_account(dry_run, &mut err); - } else if self.opt.cmd_verify_assertion { - call_result = self._relyingparty_verify_assertion(dry_run, &mut err); - } else if self.opt.cmd_verify_password { - call_result = self._relyingparty_verify_password(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("relyingparty", Some(opt)) => { + match opt.subcommand() { + ("create-auth-uri", Some(opt)) => { + call_result = self._relyingparty_create_auth_uri(opt, dry_run, &mut err); + }, + ("delete-account", Some(opt)) => { + call_result = self._relyingparty_delete_account(opt, dry_run, &mut err); + }, + ("download-account", Some(opt)) => { + call_result = self._relyingparty_download_account(opt, dry_run, &mut err); + }, + ("get-account-info", Some(opt)) => { + call_result = self._relyingparty_get_account_info(opt, dry_run, &mut err); + }, + ("get-oob-confirmation-code", Some(opt)) => { + call_result = self._relyingparty_get_oob_confirmation_code(opt, dry_run, &mut err); + }, + ("get-public-keys", Some(opt)) => { + call_result = self._relyingparty_get_public_keys(opt, dry_run, &mut err); + }, + ("get-recaptcha-param", Some(opt)) => { + call_result = self._relyingparty_get_recaptcha_param(opt, dry_run, &mut err); + }, + ("reset-password", Some(opt)) => { + call_result = self._relyingparty_reset_password(opt, dry_run, &mut err); + }, + ("set-account-info", Some(opt)) => { + call_result = self._relyingparty_set_account_info(opt, dry_run, &mut err); + }, + ("upload-account", Some(opt)) => { + call_result = self._relyingparty_upload_account(opt, dry_run, &mut err); + }, + ("verify-assertion", Some(opt)) => { + call_result = self._relyingparty_verify_assertion(opt, dry_run, &mut err); + }, + ("verify-password", Some(opt)) => { + call_result = self._relyingparty_verify_password(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("relyingparty".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -1041,7 +1098,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1054,7 +1111,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1064,37 +1121,373 @@ impl Engine { let engine = Engine { opt: opt, hub: api::IdentityToolkit::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("relyingparty", "methods: 'create-auth-uri', 'delete-account', 'download-account', 'get-account-info', 'get-oob-confirmation-code', 'get-public-keys', 'get-recaptcha-param', 'reset-password', 'set-account-info', 'upload-account', 'verify-assertion' and 'verify-password'", vec![ + ("create-auth-uri", + Some(r##"Creates the URI used by the IdP to authenticate the user."##), + "Details at http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli/relyingparty_create-auth-uri", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete-account", + Some(r##"Delete user account."##), + "Details at http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli/relyingparty_delete-account", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("download-account", + Some(r##"Batch download user accounts."##), + "Details at http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli/relyingparty_download-account", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-account-info", + Some(r##"Returns the account info."##), + "Details at http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli/relyingparty_get-account-info", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-oob-confirmation-code", + Some(r##"Get a code for user action confirmation."##), + "Details at http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli/relyingparty_get-oob-confirmation-code", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-public-keys", + Some(r##"Get token signing public key."##), + "Details at http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli/relyingparty_get-public-keys", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-recaptcha-param", + Some(r##"Get recaptcha secure param."##), + "Details at http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli/relyingparty_get-recaptcha-param", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reset-password", + Some(r##"Reset password for a user."##), + "Details at http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli/relyingparty_reset-password", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-account-info", + Some(r##"Set account info for a user."##), + "Details at http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli/relyingparty_set-account-info", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("upload-account", + Some(r##"Batch upload existing user accounts."##), + "Details at http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli/relyingparty_upload-account", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("verify-assertion", + Some(r##"Verifies the assertion returned by the IdP."##), + "Details at http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli/relyingparty_verify-assertion", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("verify-password", + Some(r##"Verifies the user entered password."##), + "Details at http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli/relyingparty_verify-password", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("identitytoolkit3") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150406") + .about("Help the third party sites to implement federated login.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_identitytoolkit3_cli") + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/identitytoolkit3/Cargo.toml b/gen/identitytoolkit3/Cargo.toml index ce4fc4555d..60fcb6c5d8 100644 --- a/gen/identitytoolkit3/Cargo.toml +++ b/gen/identitytoolkit3/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-identitytoolkit3" -version = "0.1.6+20150406" +version = "0.1.7+20150406" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with Identity Toolkit (protocol v3)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/identitytoolkit3" @@ -15,9 +15,10 @@ keywords = ["identitytoolkit", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/identitytoolkit3/README.md b/gen/identitytoolkit3/README.md index 669844d933..8e247f85ad 100644 --- a/gen/identitytoolkit3/README.md +++ b/gen/identitytoolkit3/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-identitytoolkit3` library allows access to all features of the *Google Identity Toolkit* service. -This documentation was generated from *Identity Toolkit* crate version *0.1.6+20150406*, where *20150406* is the exact revision of the *identitytoolkit:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *Identity Toolkit* crate version *0.1.7+20150406*, where *20150406* is the exact revision of the *identitytoolkit:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *Identity Toolkit* *v3* API can be found at the [official documentation site](https://developers.google.com/identity-toolkit/v3/). @@ -163,7 +163,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_identitytoolkit3/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_identitytoolkit3/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/identitytoolkit3/src/cmn.rs b/gen/identitytoolkit3/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/identitytoolkit3/src/cmn.rs +++ b/gen/identitytoolkit3/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/identitytoolkit3/src/lib.rs b/gen/identitytoolkit3/src/lib.rs index 6809eb25a1..4761423550 100644 --- a/gen/identitytoolkit3/src/lib.rs +++ b/gen/identitytoolkit3/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *Identity Toolkit* crate version *0.1.6+20150406*, where *20150406* is the exact revision of the *identitytoolkit:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *Identity Toolkit* crate version *0.1.7+20150406*, where *20150406* is the exact revision of the *identitytoolkit:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *Identity Toolkit* *v3* API can be found at the //! [official documentation site](https://developers.google.com/identity-toolkit/v3/). @@ -164,7 +164,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -173,7 +173,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -189,6 +188,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -289,7 +289,7 @@ impl<'a, C, A> IdentityToolkit<C, A> IdentityToolkit { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -298,7 +298,7 @@ impl<'a, C, A> IdentityToolkit<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1362,6 +1362,7 @@ impl<'a, C, A> RelyingpartyGetOobConfirmationCodeCall<'a, C, A> where C: BorrowM /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, GetOobConfirmationCodeResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1401,11 +1402,20 @@ impl<'a, C, A> RelyingpartyGetOobConfirmationCodeCall<'a, C, A> where C: BorrowM if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1414,7 +1424,7 @@ impl<'a, C, A> RelyingpartyGetOobConfirmationCodeCall<'a, C, A> where C: BorrowM request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -1598,7 +1608,7 @@ impl<'a, C, A> RelyingpartyGetPublicKeyCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1606,7 +1616,7 @@ impl<'a, C, A> RelyingpartyGetPublicKeyCall<'a, C, A> where C: BorrowMut<hyper:: loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -1746,6 +1756,7 @@ impl<'a, C, A> RelyingpartyCreateAuthUriCall<'a, C, A> where C: BorrowMut<hyper: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CreateAuthUriResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1785,11 +1796,20 @@ impl<'a, C, A> RelyingpartyCreateAuthUriCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1798,7 +1818,7 @@ impl<'a, C, A> RelyingpartyCreateAuthUriCall<'a, C, A> where C: BorrowMut<hyper: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -1950,6 +1970,7 @@ impl<'a, C, A> RelyingpartyVerifyAssertionCall<'a, C, A> where C: BorrowMut<hype /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, VerifyAssertionResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1989,11 +2010,20 @@ impl<'a, C, A> RelyingpartyVerifyAssertionCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2002,7 +2032,7 @@ impl<'a, C, A> RelyingpartyVerifyAssertionCall<'a, C, A> where C: BorrowMut<hype request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -2154,6 +2184,7 @@ impl<'a, C, A> RelyingpartyUploadAccountCall<'a, C, A> where C: BorrowMut<hyper: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, UploadAccountResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2193,11 +2224,20 @@ impl<'a, C, A> RelyingpartyUploadAccountCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2206,7 +2246,7 @@ impl<'a, C, A> RelyingpartyUploadAccountCall<'a, C, A> where C: BorrowMut<hyper: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -2358,6 +2398,7 @@ impl<'a, C, A> RelyingpartyGetAccountInfoCall<'a, C, A> where C: BorrowMut<hyper /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, GetAccountInfoResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2397,11 +2438,20 @@ impl<'a, C, A> RelyingpartyGetAccountInfoCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2410,7 +2460,7 @@ impl<'a, C, A> RelyingpartyGetAccountInfoCall<'a, C, A> where C: BorrowMut<hyper request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -2562,6 +2612,7 @@ impl<'a, C, A> RelyingpartyResetPasswordCall<'a, C, A> where C: BorrowMut<hyper: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ResetPasswordResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2601,11 +2652,20 @@ impl<'a, C, A> RelyingpartyResetPasswordCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2614,7 +2674,7 @@ impl<'a, C, A> RelyingpartyResetPasswordCall<'a, C, A> where C: BorrowMut<hyper: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -2766,6 +2826,7 @@ impl<'a, C, A> RelyingpartyDownloadAccountCall<'a, C, A> where C: BorrowMut<hype /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, DownloadAccountResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2805,11 +2866,20 @@ impl<'a, C, A> RelyingpartyDownloadAccountCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2818,7 +2888,7 @@ impl<'a, C, A> RelyingpartyDownloadAccountCall<'a, C, A> where C: BorrowMut<hype request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -2970,6 +3040,7 @@ impl<'a, C, A> RelyingpartySetAccountInfoCall<'a, C, A> where C: BorrowMut<hyper /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SetAccountInfoResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3009,11 +3080,20 @@ impl<'a, C, A> RelyingpartySetAccountInfoCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3022,7 +3102,7 @@ impl<'a, C, A> RelyingpartySetAccountInfoCall<'a, C, A> where C: BorrowMut<hyper request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -3174,6 +3254,7 @@ impl<'a, C, A> RelyingpartyDeleteAccountCall<'a, C, A> where C: BorrowMut<hyper: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, DeleteAccountResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3213,11 +3294,20 @@ impl<'a, C, A> RelyingpartyDeleteAccountCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3226,7 +3316,7 @@ impl<'a, C, A> RelyingpartyDeleteAccountCall<'a, C, A> where C: BorrowMut<hyper: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -3410,7 +3500,7 @@ impl<'a, C, A> RelyingpartyGetRecaptchaParamCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3418,7 +3508,7 @@ impl<'a, C, A> RelyingpartyGetRecaptchaParamCall<'a, C, A> where C: BorrowMut<hy loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -3558,6 +3648,7 @@ impl<'a, C, A> RelyingpartyVerifyPasswordCall<'a, C, A> where C: BorrowMut<hyper /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, VerifyPasswordResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3597,11 +3688,20 @@ impl<'a, C, A> RelyingpartyVerifyPasswordCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3610,7 +3710,7 @@ impl<'a, C, A> RelyingpartyVerifyPasswordCall<'a, C, A> where C: BorrowMut<hyper request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) diff --git a/gen/licensing1-cli/Cargo.toml b/gen/licensing1-cli/Cargo.toml index bc5ae86f85..0c0e809cb7 100644 --- a/gen/licensing1-cli/Cargo.toml +++ b/gen/licensing1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-licensing1-cli" -version = "0.1.0+20140122" +version = "0.2.0+20140122" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with licensing (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/licensing1-cli" @@ -17,15 +17,14 @@ keywords = ["licensing", "google", "cli"] name = "licensing1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-licensing1] path = "../licensing1" diff --git a/gen/licensing1-cli/README.md b/gen/licensing1-cli/README.md index b18703ddfa..09cbadb47e 100644 --- a/gen/licensing1-cli/README.md +++ b/gen/licensing1-cli/README.md @@ -10,27 +10,29 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *licensing* API can be found at the +[official documentation site](https://developers.google.com/google-apps/licensing/). + # Usage -This documentation was generated from the *licensing* API at revision *20140122*. The CLI is at version *0.1.0*. +This documentation was generated from the *licensing* API at revision *20140122*. The CLI is at version *0.2.0*. ```bash - licensing1 [options] license-assignments delete <product-id> <sku-id> <user-id> [-p <v>...] - licensing1 [options] license-assignments get <product-id> <sku-id> <user-id> [-p <v>...] [-o <out>] - licensing1 [options] license-assignments insert <product-id> <sku-id> -r <kv>... [-p <v>...] [-o <out>] - licensing1 [options] license-assignments list-for-product <product-id> <customer-id> [-p <v>...] [-o <out>] - licensing1 [options] license-assignments list-for-product-and-sku <product-id> <sku-id> <customer-id> [-p <v>...] [-o <out>] - licensing1 [options] license-assignments patch <product-id> <sku-id> <user-id> -r <kv>... [-p <v>...] [-o <out>] - licensing1 [options] license-assignments update <product-id> <sku-id> <user-id> -r <kv>... [-p <v>...] [-o <out>] +licensing1 [options] + license-assignments + delete <product-id> <sku-id> <user-id> [-p <v>]... + get <product-id> <sku-id> <user-id> [-p <v>]... [-o <out>] + insert <product-id> <sku-id> (-r <kv>)... [-p <v>]... [-o <out>] + list-for-product <product-id> <customer-id> [-p <v>]... [-o <out>] + list-for-product-and-sku <product-id> <sku-id> <customer-id> [-p <v>]... [-o <out>] + patch <product-id> <sku-id> <user-id> (-r <kv>)... [-p <v>]... [-o <out>] + update <product-id> <sku-id> <user-id> (-r <kv>)... [-p <v>]... [-o <out>] licensing1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_licensing1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/licensing1-cli/mkdocs.yml b/gen/licensing1-cli/mkdocs.yml index 0dc62eb6b1..806e5c793a 100644 --- a/gen/licensing1-cli/mkdocs.yml +++ b/gen/licensing1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: licensing v0.1.0+20140122 +site_name: licensing v0.2.0+20140122 site_url: http://byron.github.io/google-apis-rs/google-licensing1-cli site_description: Write integrating applications with bcore diff --git a/gen/licensing1-cli/src/cmn.rs b/gen/licensing1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/licensing1-cli/src/cmn.rs +++ b/gen/licensing1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/licensing1-cli/src/main.rs b/gen/licensing1-cli/src/main.rs index 76574916d0..7150fdfc03 100644 --- a/gen/licensing1-cli/src/main.rs +++ b/gen/licensing1-cli/src/main.rs @@ -2,165 +2,148 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_licensing1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - licensing1 [options] license-assignments delete <product-id> <sku-id> <user-id> [-p <v>...] - licensing1 [options] license-assignments get <product-id> <sku-id> <user-id> [-p <v>...] [-o <out>] - licensing1 [options] license-assignments insert <product-id> <sku-id> -r <kv>... [-p <v>...] [-o <out>] - licensing1 [options] license-assignments list-for-product <product-id> <customer-id> [-p <v>...] [-o <out>] - licensing1 [options] license-assignments list-for-product-and-sku <product-id> <sku-id> <customer-id> [-p <v>...] [-o <out>] - licensing1 [options] license-assignments patch <product-id> <sku-id> <user-id> -r <kv>... [-p <v>...] [-o <out>] - licensing1 [options] license-assignments update <product-id> <sku-id> <user-id> -r <kv>... [-p <v>...] [-o <out>] - licensing1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_licensing1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Licensing<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _license_assignments_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.license_assignments().delete(&self.opt.arg_product_id, &self.opt.arg_sku_id, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _license_assignments_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.license_assignments().delete(opt.value_of("product-id").unwrap_or(""), opt.value_of("sku-id").unwrap_or(""), opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _license_assignments_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.license_assignments().get(&self.opt.arg_product_id, &self.opt.arg_sku_id, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _license_assignments_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.license_assignments().get(opt.value_of("product-id").unwrap_or(""), opt.value_of("sku-id").unwrap_or(""), opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _license_assignments_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _license_assignments_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::LicenseAssignmentInsert::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -179,58 +162,63 @@ impl Engine { request.user_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["user-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.license_assignments().insert(request, &self.opt.arg_product_id, &self.opt.arg_sku_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.license_assignments().insert(request, opt.value_of("product-id").unwrap_or(""), opt.value_of("sku-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _license_assignments_list_for_product(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.license_assignments().list_for_product(&self.opt.arg_product_id, &self.opt.arg_customer_id); - for parg in self.opt.arg_v.iter() { + fn _license_assignments_list_for_product(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.license_assignments().list_for_product(opt.value_of("product-id").unwrap_or(""), opt.value_of("customer-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -239,50 +227,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _license_assignments_list_for_product_and_sku(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.license_assignments().list_for_product_and_sku(&self.opt.arg_product_id, &self.opt.arg_sku_id, &self.opt.arg_customer_id); - for parg in self.opt.arg_v.iter() { + fn _license_assignments_list_for_product_and_sku(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.license_assignments().list_for_product_and_sku(opt.value_of("product-id").unwrap_or(""), opt.value_of("sku-id").unwrap_or(""), opt.value_of("customer-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -291,52 +283,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _license_assignments_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _license_assignments_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::LicenseAssignment::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -370,60 +366,65 @@ impl Engine { request.product_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etags", "kind", "product-id", "self-link", "sku-id", "user-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.license_assignments().patch(request, &self.opt.arg_product_id, &self.opt.arg_sku_id, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.license_assignments().patch(request, opt.value_of("product-id").unwrap_or(""), opt.value_of("sku-id").unwrap_or(""), opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _license_assignments_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _license_assignments_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::LicenseAssignment::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -457,93 +458,113 @@ impl Engine { request.product_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etags", "kind", "product-id", "self-link", "sku-id", "user-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.license_assignments().update(request, &self.opt.arg_product_id, &self.opt.arg_sku_id, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.license_assignments().update(request, opt.value_of("product-id").unwrap_or(""), opt.value_of("sku-id").unwrap_or(""), opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_license_assignments { - if self.opt.cmd_delete { - call_result = self._license_assignments_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._license_assignments_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._license_assignments_insert(dry_run, &mut err); - } else if self.opt.cmd_list_for_product { - call_result = self._license_assignments_list_for_product(dry_run, &mut err); - } else if self.opt.cmd_list_for_product_and_sku { - call_result = self._license_assignments_list_for_product_and_sku(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._license_assignments_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._license_assignments_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("license-assignments", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._license_assignments_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._license_assignments_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._license_assignments_insert(opt, dry_run, &mut err); + }, + ("list-for-product", Some(opt)) => { + call_result = self._license_assignments_list_for_product(opt, dry_run, &mut err); + }, + ("list-for-product-and-sku", Some(opt)) => { + call_result = self._license_assignments_list_for_product_and_sku(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._license_assignments_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._license_assignments_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("license-assignments".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -556,7 +577,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -569,7 +590,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -579,37 +600,364 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Licensing::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("license-assignments", "methods: 'delete', 'get', 'insert', 'list-for-product', 'list-for-product-and-sku', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Revoke License."##), + "Details at http://byron.github.io/google-apis-rs/google_licensing1_cli/license-assignments_delete", + vec![ + (Some(r##"product-id"##), + None, + Some(r##"Name for product"##), + Some(true), + Some(false)), + + (Some(r##"sku-id"##), + None, + Some(r##"Name for sku"##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"email id or unique Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Get license assignment of a particular product and sku for a user"##), + "Details at http://byron.github.io/google-apis-rs/google_licensing1_cli/license-assignments_get", + vec![ + (Some(r##"product-id"##), + None, + Some(r##"Name for product"##), + Some(true), + Some(false)), + + (Some(r##"sku-id"##), + None, + Some(r##"Name for sku"##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"email id or unique Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Assign License."##), + "Details at http://byron.github.io/google-apis-rs/google_licensing1_cli/license-assignments_insert", + vec![ + (Some(r##"product-id"##), + None, + Some(r##"Name for product"##), + Some(true), + Some(false)), + + (Some(r##"sku-id"##), + None, + Some(r##"Name for sku"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-for-product", + Some(r##"List license assignments for given product of the customer."##), + "Details at http://byron.github.io/google-apis-rs/google_licensing1_cli/license-assignments_list-for-product", + vec![ + (Some(r##"product-id"##), + None, + Some(r##"Name for product"##), + Some(true), + Some(false)), + + (Some(r##"customer-id"##), + None, + Some(r##"CustomerId represents the customer for whom licenseassignments are queried"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-for-product-and-sku", + Some(r##"List license assignments for given product and sku of the customer."##), + "Details at http://byron.github.io/google-apis-rs/google_licensing1_cli/license-assignments_list-for-product-and-sku", + vec![ + (Some(r##"product-id"##), + None, + Some(r##"Name for product"##), + Some(true), + Some(false)), + + (Some(r##"sku-id"##), + None, + Some(r##"Name for sku"##), + Some(true), + Some(false)), + + (Some(r##"customer-id"##), + None, + Some(r##"CustomerId represents the customer for whom licenseassignments are queried"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Assign License. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_licensing1_cli/license-assignments_patch", + vec![ + (Some(r##"product-id"##), + None, + Some(r##"Name for product"##), + Some(true), + Some(false)), + + (Some(r##"sku-id"##), + None, + Some(r##"Name for sku for which license would be revoked"##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"email id or unique Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Assign License."##), + "Details at http://byron.github.io/google-apis-rs/google_licensing1_cli/license-assignments_update", + vec![ + (Some(r##"product-id"##), + None, + Some(r##"Name for product"##), + Some(true), + Some(false)), + + (Some(r##"sku-id"##), + None, + Some(r##"Name for sku for which license would be revoked"##), + Some(true), + Some(false)), + + (Some(r##"user-id"##), + None, + Some(r##"email id or unique Id of the user"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("licensing1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20140122") + .about("Licensing API to view and manage license for your domain.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_licensing1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/licensing1/Cargo.toml b/gen/licensing1/Cargo.toml index eead844319..f78047a854 100644 --- a/gen/licensing1/Cargo.toml +++ b/gen/licensing1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-licensing1" -version = "0.1.6+20140122" +version = "0.1.7+20140122" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with licensing (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/licensing1" @@ -15,9 +15,10 @@ keywords = ["licensing", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/licensing1/README.md b/gen/licensing1/README.md index a191f36a2e..f598609aee 100644 --- a/gen/licensing1/README.md +++ b/gen/licensing1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-licensing1` library allows access to all features of the *Google licensing* service. -This documentation was generated from *licensing* crate version *0.1.6+20140122*, where *20140122* is the exact revision of the *licensing:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *licensing* crate version *0.1.7+20140122*, where *20140122* is the exact revision of the *licensing:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *licensing* *v1* API can be found at the [official documentation site](https://developers.google.com/google-apps/licensing/). @@ -165,7 +165,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_licensing1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_licensing1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/licensing1/src/cmn.rs b/gen/licensing1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/licensing1/src/cmn.rs +++ b/gen/licensing1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/licensing1/src/lib.rs b/gen/licensing1/src/lib.rs index 2a4ad91a64..899003ad54 100644 --- a/gen/licensing1/src/lib.rs +++ b/gen/licensing1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *licensing* crate version *0.1.6+20140122*, where *20140122* is the exact revision of the *licensing:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *licensing* crate version *0.1.7+20140122*, where *20140122* is the exact revision of the *licensing:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *licensing* *v1* API can be found at the //! [official documentation site](https://developers.google.com/google-apps/licensing/). @@ -166,7 +166,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -175,7 +175,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -191,6 +190,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -309,7 +309,7 @@ impl<'a, C, A> Licensing<C, A> Licensing { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -318,7 +318,7 @@ impl<'a, C, A> Licensing<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -727,7 +727,7 @@ impl<'a, C, A> LicenseAssignmentDeleteCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -749,7 +749,7 @@ impl<'a, C, A> LicenseAssignmentDeleteCall<'a, C, A> where C: BorrowMut<hyper::C access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -988,7 +988,7 @@ impl<'a, C, A> LicenseAssignmentListForProductCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1010,7 +1010,7 @@ impl<'a, C, A> LicenseAssignmentListForProductCall<'a, C, A> where C: BorrowMut< access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1255,7 +1255,7 @@ impl<'a, C, A> LicenseAssignmentGetCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1277,7 +1277,7 @@ impl<'a, C, A> LicenseAssignmentGetCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1528,7 +1528,7 @@ impl<'a, C, A> LicenseAssignmentListForProductAndSkuCall<'a, C, A> where C: Borr if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1550,7 +1550,7 @@ impl<'a, C, A> LicenseAssignmentListForProductAndSkuCall<'a, C, A> where C: Borr access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1755,6 +1755,7 @@ impl<'a, C, A> LicenseAssignmentUpdateCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LicenseAssignment)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1812,11 +1813,20 @@ impl<'a, C, A> LicenseAssignmentUpdateCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1839,7 +1849,7 @@ impl<'a, C, A> LicenseAssignmentUpdateCall<'a, C, A> where C: BorrowMut<hyper::C request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2042,6 +2052,7 @@ impl<'a, C, A> LicenseAssignmentPatchCall<'a, C, A> where C: BorrowMut<hyper::Cl /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LicenseAssignment)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2099,11 +2110,20 @@ impl<'a, C, A> LicenseAssignmentPatchCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2126,7 +2146,7 @@ impl<'a, C, A> LicenseAssignmentPatchCall<'a, C, A> where C: BorrowMut<hyper::Cl request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2328,6 +2348,7 @@ impl<'a, C, A> LicenseAssignmentInsertCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LicenseAssignment)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2384,11 +2405,20 @@ impl<'a, C, A> LicenseAssignmentInsertCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2411,7 +2441,7 @@ impl<'a, C, A> LicenseAssignmentInsertCall<'a, C, A> where C: BorrowMut<hyper::C request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) diff --git a/gen/logging1_beta3-cli/Cargo.toml b/gen/logging1_beta3-cli/Cargo.toml index dd03fc9d31..c06a2a634f 100644 --- a/gen/logging1_beta3-cli/Cargo.toml +++ b/gen/logging1_beta3-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-logging1_beta3-cli" -version = "0.1.0+20150326" +version = "0.2.0+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with logging (protocol v1beta3)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/logging1_beta3-cli" @@ -16,15 +16,14 @@ keywords = ["logging", "google", "cli"] name = "logging1-beta3" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-logging1_beta3] path = "../logging1_beta3" diff --git a/gen/logging1_beta3-cli/README.md b/gen/logging1_beta3-cli/README.md index a66499aaa5..00d4642b10 100644 --- a/gen/logging1_beta3-cli/README.md +++ b/gen/logging1_beta3-cli/README.md @@ -12,33 +12,32 @@ If data-structures are requested, these will be returned as pretty-printed JSON, # Usage -This documentation was generated from the *logging* API at revision *20150326*. The CLI is at version *0.1.0*. +This documentation was generated from the *logging* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - logging1-beta3 [options] projects log-services-indexes-list <projects-id> <log-services-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects log-services-list <projects-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects log-services-sinks-create <projects-id> <log-services-id> -r <kv>... [-p <v>...] [-o <out>] - logging1-beta3 [options] projects log-services-sinks-delete <projects-id> <log-services-id> <sinks-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects log-services-sinks-get <projects-id> <log-services-id> <sinks-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects log-services-sinks-list <projects-id> <log-services-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects log-services-sinks-update <projects-id> <log-services-id> <sinks-id> -r <kv>... [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-delete <projects-id> <logs-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-entries-write <projects-id> <logs-id> -r <kv>... [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-list <projects-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-sinks-create <projects-id> <logs-id> -r <kv>... [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-sinks-delete <projects-id> <logs-id> <sinks-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-sinks-get <projects-id> <logs-id> <sinks-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-sinks-list <projects-id> <logs-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-sinks-update <projects-id> <logs-id> <sinks-id> -r <kv>... [-p <v>...] [-o <out>] +logging1-beta3 [options] + projects + log-services-indexes-list <projects-id> <log-services-id> [-p <v>]... [-o <out>] + log-services-list <projects-id> [-p <v>]... [-o <out>] + log-services-sinks-create <projects-id> <log-services-id> (-r <kv>)... [-p <v>]... [-o <out>] + log-services-sinks-delete <projects-id> <log-services-id> <sinks-id> [-p <v>]... [-o <out>] + log-services-sinks-get <projects-id> <log-services-id> <sinks-id> [-p <v>]... [-o <out>] + log-services-sinks-list <projects-id> <log-services-id> [-p <v>]... [-o <out>] + log-services-sinks-update <projects-id> <log-services-id> <sinks-id> (-r <kv>)... [-p <v>]... [-o <out>] + logs-delete <projects-id> <logs-id> [-p <v>]... [-o <out>] + logs-entries-write <projects-id> <logs-id> (-r <kv>)... [-p <v>]... [-o <out>] + logs-list <projects-id> [-p <v>]... [-o <out>] + logs-sinks-create <projects-id> <logs-id> (-r <kv>)... [-p <v>]... [-o <out>] + logs-sinks-delete <projects-id> <logs-id> <sinks-id> [-p <v>]... [-o <out>] + logs-sinks-get <projects-id> <logs-id> <sinks-id> [-p <v>]... [-o <out>] + logs-sinks-list <projects-id> <logs-id> [-p <v>]... [-o <out>] + logs-sinks-update <projects-id> <logs-id> <sinks-id> (-r <kv>)... [-p <v>]... [-o <out>] logging1-beta3 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/logging1_beta3-cli/mkdocs.yml b/gen/logging1_beta3-cli/mkdocs.yml index 596283d2b5..2a05c3fac8 100644 --- a/gen/logging1_beta3-cli/mkdocs.yml +++ b/gen/logging1_beta3-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: logging v0.1.0+20150326 +site_name: logging v0.2.0+20150326 site_url: http://byron.github.io/google-apis-rs/google-logging1_beta3-cli site_description: Write integrating applications with bcore diff --git a/gen/logging1_beta3-cli/src/cmn.rs b/gen/logging1_beta3-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/logging1_beta3-cli/src/cmn.rs +++ b/gen/logging1_beta3-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/logging1_beta3-cli/src/main.rs b/gen/logging1_beta3-cli/src/main.rs index 2d42401238..bc8b8bc574 100644 --- a/gen/logging1_beta3-cli/src/main.rs +++ b/gen/logging1_beta3-cli/src/main.rs @@ -2,81 +2,53 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_logging1_beta3 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - logging1-beta3 [options] projects log-services-indexes-list <projects-id> <log-services-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects log-services-list <projects-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects log-services-sinks-create <projects-id> <log-services-id> -r <kv>... [-p <v>...] [-o <out>] - logging1-beta3 [options] projects log-services-sinks-delete <projects-id> <log-services-id> <sinks-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects log-services-sinks-get <projects-id> <log-services-id> <sinks-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects log-services-sinks-list <projects-id> <log-services-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects log-services-sinks-update <projects-id> <log-services-id> <sinks-id> -r <kv>... [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-delete <projects-id> <logs-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-entries-write <projects-id> <logs-id> -r <kv>... [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-list <projects-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-sinks-create <projects-id> <logs-id> -r <kv>... [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-sinks-delete <projects-id> <logs-id> <sinks-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-sinks-get <projects-id> <logs-id> <sinks-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-sinks-list <projects-id> <logs-id> [-p <v>...] [-o <out>] - logging1-beta3 [options] projects logs-sinks-update <projects-id> <logs-id> <sinks-id> -r <kv>... [-p <v>...] [-o <out>] - logging1-beta3 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Logging<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _projects_log_services_indexes_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().log_services_indexes_list(&self.opt.arg_projects_id, &self.opt.arg_log_services_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _projects_log_services_indexes_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().log_services_indexes_list(opt.value_of("projects-id").unwrap_or(""), opt.value_of("log-services-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -94,56 +66,54 @@ impl Engine { "depth" => { call = call.depth(arg_from_str(value.unwrap_or("-0"), err, "depth", "integer")); }, - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "depth", "index-prefix", "log", "page-size"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_log_services_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().log_services_list(&self.opt.arg_projects_id); - for parg in self.opt.arg_v.iter() { + fn _projects_log_services_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().log_services_list(opt.value_of("projects-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -155,58 +125,56 @@ impl Engine { "log" => { call = call.log(value.unwrap_or("")); }, - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "log", "page-size"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_log_services_sinks_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _projects_log_services_sinks_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::LogSink::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -228,222 +196,215 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["destination", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().log_services_sinks_create(request, &self.opt.arg_projects_id, &self.opt.arg_log_services_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().log_services_sinks_create(request, opt.value_of("projects-id").unwrap_or(""), opt.value_of("log-services-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_log_services_sinks_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().log_services_sinks_delete(&self.opt.arg_projects_id, &self.opt.arg_log_services_id, &self.opt.arg_sinks_id); - for parg in self.opt.arg_v.iter() { + fn _projects_log_services_sinks_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().log_services_sinks_delete(opt.value_of("projects-id").unwrap_or(""), opt.value_of("log-services-id").unwrap_or(""), opt.value_of("sinks-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_log_services_sinks_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().log_services_sinks_get(&self.opt.arg_projects_id, &self.opt.arg_log_services_id, &self.opt.arg_sinks_id); - for parg in self.opt.arg_v.iter() { + fn _projects_log_services_sinks_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().log_services_sinks_get(opt.value_of("projects-id").unwrap_or(""), opt.value_of("log-services-id").unwrap_or(""), opt.value_of("sinks-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_log_services_sinks_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().log_services_sinks_list(&self.opt.arg_projects_id, &self.opt.arg_log_services_id); - for parg in self.opt.arg_v.iter() { + fn _projects_log_services_sinks_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().log_services_sinks_list(opt.value_of("projects-id").unwrap_or(""), opt.value_of("log-services-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_log_services_sinks_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _projects_log_services_sinks_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::LogSink::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -465,118 +426,115 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["destination", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().log_services_sinks_update(request, &self.opt.arg_projects_id, &self.opt.arg_log_services_id, &self.opt.arg_sinks_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().log_services_sinks_update(request, opt.value_of("projects-id").unwrap_or(""), opt.value_of("log-services-id").unwrap_or(""), opt.value_of("sinks-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_logs_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().logs_delete(&self.opt.arg_projects_id, &self.opt.arg_logs_id); - for parg in self.opt.arg_v.iter() { + fn _projects_logs_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().logs_delete(opt.value_of("projects-id").unwrap_or(""), opt.value_of("logs-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_logs_entries_write(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _projects_logs_entries_write(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::WriteLogEntriesRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -599,64 +557,63 @@ impl Engine { request.common_labels.as_mut().unwrap().insert(key.to_string(), value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["common-labels"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().logs_entries_write(request, &self.opt.arg_projects_id, &self.opt.arg_logs_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().logs_entries_write(request, opt.value_of("projects-id").unwrap_or(""), opt.value_of("logs-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_logs_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().logs_list(&self.opt.arg_projects_id); - for parg in self.opt.arg_v.iter() { + fn _projects_logs_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().logs_list(opt.value_of("projects-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "service-name" => { @@ -671,58 +628,56 @@ impl Engine { "page-size" => { call = call.page_size(arg_from_str(value.unwrap_or("-0"), err, "page-size", "integer")); }, - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "service-name", "service-index-prefix", "page-size"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_logs_sinks_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _projects_logs_sinks_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::LogSink::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -744,222 +699,215 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["destination", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().logs_sinks_create(request, &self.opt.arg_projects_id, &self.opt.arg_logs_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().logs_sinks_create(request, opt.value_of("projects-id").unwrap_or(""), opt.value_of("logs-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_logs_sinks_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().logs_sinks_delete(&self.opt.arg_projects_id, &self.opt.arg_logs_id, &self.opt.arg_sinks_id); - for parg in self.opt.arg_v.iter() { + fn _projects_logs_sinks_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().logs_sinks_delete(opt.value_of("projects-id").unwrap_or(""), opt.value_of("logs-id").unwrap_or(""), opt.value_of("sinks-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_logs_sinks_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().logs_sinks_get(&self.opt.arg_projects_id, &self.opt.arg_logs_id, &self.opt.arg_sinks_id); - for parg in self.opt.arg_v.iter() { + fn _projects_logs_sinks_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().logs_sinks_get(opt.value_of("projects-id").unwrap_or(""), opt.value_of("logs-id").unwrap_or(""), opt.value_of("sinks-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_logs_sinks_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().logs_sinks_list(&self.opt.arg_projects_id, &self.opt.arg_logs_id); - for parg in self.opt.arg_v.iter() { + fn _projects_logs_sinks_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().logs_sinks_list(opt.value_of("projects-id").unwrap_or(""), opt.value_of("logs-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_logs_sinks_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _projects_logs_sinks_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::LogSink::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -981,115 +929,137 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["destination", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().logs_sinks_update(request, &self.opt.arg_projects_id, &self.opt.arg_logs_id, &self.opt.arg_sinks_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().logs_sinks_update(request, opt.value_of("projects-id").unwrap_or(""), opt.value_of("logs-id").unwrap_or(""), opt.value_of("sinks-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "$-xgafv" - |"access-token" - |"alt" - |"bearer-token" - |"callback" - |"fields" - |"key" - |"oauth-token" - |"pp" - |"pretty-print" - |"quota-user" => { - let map = [ - ("$-xgafv", "$.xgafv"), - ("access-token", "access_token"), - ("bearer-token", "bearer_token"), - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_projects { - if self.opt.cmd_log_services_indexes_list { - call_result = self._projects_log_services_indexes_list(dry_run, &mut err); - } else if self.opt.cmd_log_services_list { - call_result = self._projects_log_services_list(dry_run, &mut err); - } else if self.opt.cmd_log_services_sinks_create { - call_result = self._projects_log_services_sinks_create(dry_run, &mut err); - } else if self.opt.cmd_log_services_sinks_delete { - call_result = self._projects_log_services_sinks_delete(dry_run, &mut err); - } else if self.opt.cmd_log_services_sinks_get { - call_result = self._projects_log_services_sinks_get(dry_run, &mut err); - } else if self.opt.cmd_log_services_sinks_list { - call_result = self._projects_log_services_sinks_list(dry_run, &mut err); - } else if self.opt.cmd_log_services_sinks_update { - call_result = self._projects_log_services_sinks_update(dry_run, &mut err); - } else if self.opt.cmd_logs_delete { - call_result = self._projects_logs_delete(dry_run, &mut err); - } else if self.opt.cmd_logs_entries_write { - call_result = self._projects_logs_entries_write(dry_run, &mut err); - } else if self.opt.cmd_logs_list { - call_result = self._projects_logs_list(dry_run, &mut err); - } else if self.opt.cmd_logs_sinks_create { - call_result = self._projects_logs_sinks_create(dry_run, &mut err); - } else if self.opt.cmd_logs_sinks_delete { - call_result = self._projects_logs_sinks_delete(dry_run, &mut err); - } else if self.opt.cmd_logs_sinks_get { - call_result = self._projects_logs_sinks_get(dry_run, &mut err); - } else if self.opt.cmd_logs_sinks_list { - call_result = self._projects_logs_sinks_list(dry_run, &mut err); - } else if self.opt.cmd_logs_sinks_update { - call_result = self._projects_logs_sinks_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("projects", Some(opt)) => { + match opt.subcommand() { + ("log-services-indexes-list", Some(opt)) => { + call_result = self._projects_log_services_indexes_list(opt, dry_run, &mut err); + }, + ("log-services-list", Some(opt)) => { + call_result = self._projects_log_services_list(opt, dry_run, &mut err); + }, + ("log-services-sinks-create", Some(opt)) => { + call_result = self._projects_log_services_sinks_create(opt, dry_run, &mut err); + }, + ("log-services-sinks-delete", Some(opt)) => { + call_result = self._projects_log_services_sinks_delete(opt, dry_run, &mut err); + }, + ("log-services-sinks-get", Some(opt)) => { + call_result = self._projects_log_services_sinks_get(opt, dry_run, &mut err); + }, + ("log-services-sinks-list", Some(opt)) => { + call_result = self._projects_log_services_sinks_list(opt, dry_run, &mut err); + }, + ("log-services-sinks-update", Some(opt)) => { + call_result = self._projects_log_services_sinks_update(opt, dry_run, &mut err); + }, + ("logs-delete", Some(opt)) => { + call_result = self._projects_logs_delete(opt, dry_run, &mut err); + }, + ("logs-entries-write", Some(opt)) => { + call_result = self._projects_logs_entries_write(opt, dry_run, &mut err); + }, + ("logs-list", Some(opt)) => { + call_result = self._projects_logs_list(opt, dry_run, &mut err); + }, + ("logs-sinks-create", Some(opt)) => { + call_result = self._projects_logs_sinks_create(opt, dry_run, &mut err); + }, + ("logs-sinks-delete", Some(opt)) => { + call_result = self._projects_logs_sinks_delete(opt, dry_run, &mut err); + }, + ("logs-sinks-get", Some(opt)) => { + call_result = self._projects_logs_sinks_get(opt, dry_run, &mut err); + }, + ("logs-sinks-list", Some(opt)) => { + call_result = self._projects_logs_sinks_list(opt, dry_run, &mut err); + }, + ("logs-sinks-update", Some(opt)) => { + call_result = self._projects_logs_sinks_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("projects".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -1102,7 +1072,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1115,7 +1085,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1125,37 +1095,602 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Logging::new(client, auth), + gp: vec!["$-xgafv", "access-token", "alt", "bearer-token", "callback", "fields", "key", "oauth-token", "pp", "pretty-print", "quota-user"], + gpm: vec![ + ("$-xgafv", "$.xgafv"), + ("access-token", "access_token"), + ("bearer-token", "bearer_token"), + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("projects", "methods: 'log-services-indexes-list', 'log-services-list', 'log-services-sinks-create', 'log-services-sinks-delete', 'log-services-sinks-get', 'log-services-sinks-list', 'log-services-sinks-update', 'logs-delete', 'logs-entries-write', 'logs-list', 'logs-sinks-create', 'logs-sinks-delete', 'logs-sinks-get', 'logs-sinks-list' and 'logs-sinks-update'", vec![ + ("log-services-indexes-list", + Some(r##"Lists log service indexes associated with a log service."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_log-services-indexes-list", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `serviceName`. A log service resource of the form `/projects/*/logServices/*`. The service indexes of the log service are returned. Example: `"/projects/myProj/logServices/appengine.googleapis.com"`."##), + Some(true), + Some(false)), + + (Some(r##"log-services-id"##), + None, + Some(r##"Part of `serviceName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("log-services-list", + Some(r##"Lists log services associated with log entries ingested for a project."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_log-services-list", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `projectName`. The project resource whose services are to be listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("log-services-sinks-create", + Some(r##"Creates the specified log service sink resource."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_log-services-sinks-create", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `serviceName`. The name of the service in which to create a sink."##), + Some(true), + Some(false)), + + (Some(r##"log-services-id"##), + None, + Some(r##"Part of `serviceName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("log-services-sinks-delete", + Some(r##"Deletes the specified log service sink."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_log-services-sinks-delete", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `sinkName`. The name of the sink to delete."##), + Some(true), + Some(false)), + + (Some(r##"log-services-id"##), + None, + Some(r##"Part of `sinkName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"sinks-id"##), + None, + Some(r##"Part of `sinkName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("log-services-sinks-get", + Some(r##"Gets the specified log service sink resource."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_log-services-sinks-get", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `sinkName`. The name of the sink to return."##), + Some(true), + Some(false)), + + (Some(r##"log-services-id"##), + None, + Some(r##"Part of `sinkName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"sinks-id"##), + None, + Some(r##"Part of `sinkName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("log-services-sinks-list", + Some(r##"Lists log service sinks associated with the specified service."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_log-services-sinks-list", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `serviceName`. The name of the service for which to list sinks."##), + Some(true), + Some(false)), + + (Some(r##"log-services-id"##), + None, + Some(r##"Part of `serviceName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("log-services-sinks-update", + Some(r##"Creates or update the specified log service sink resource."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_log-services-sinks-update", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `sinkName`. The name of the sink to update."##), + Some(true), + Some(false)), + + (Some(r##"log-services-id"##), + None, + Some(r##"Part of `sinkName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"sinks-id"##), + None, + Some(r##"Part of `sinkName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("logs-delete", + Some(r##"Deletes the specified log resource and all log entries contained in it."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_logs-delete", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `logName`. The log resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"logs-id"##), + None, + Some(r##"Part of `logName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("logs-entries-write", + Some(r##"Creates one or more log entries in a log. You must supply a list of `LogEntry` objects, named `entries`. Each `LogEntry` object must contain a payload object and a `LogEntryMetadata` object that describes the entry. You must fill in all the fields of the entry, metadata, and payload. You can also supply a map, `commonLabels`, that supplies default (key, value) data for the `entries[].metadata.labels` maps, saving you the trouble of creating identical copies for each entry."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_logs-entries-write", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `logName`. The name of the log resource into which to insert the log entries."##), + Some(true), + Some(false)), + + (Some(r##"logs-id"##), + None, + Some(r##"Part of `logName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("logs-list", + Some(r##"Lists log resources belonging to the specified project."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_logs-list", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `projectName`. The project name for which to list the log resources."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("logs-sinks-create", + Some(r##"Creates the specified log sink resource."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_logs-sinks-create", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `logName`. The log in which to create a sink resource."##), + Some(true), + Some(false)), + + (Some(r##"logs-id"##), + None, + Some(r##"Part of `logName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("logs-sinks-delete", + Some(r##"Deletes the specified log sink resource."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_logs-sinks-delete", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `sinkName`. The name of the sink to delete."##), + Some(true), + Some(false)), + + (Some(r##"logs-id"##), + None, + Some(r##"Part of `sinkName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"sinks-id"##), + None, + Some(r##"Part of `sinkName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("logs-sinks-get", + Some(r##"Gets the specified log sink resource."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_logs-sinks-get", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `sinkName`. The name of the sink resource to return."##), + Some(true), + Some(false)), + + (Some(r##"logs-id"##), + None, + Some(r##"Part of `sinkName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"sinks-id"##), + None, + Some(r##"Part of `sinkName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("logs-sinks-list", + Some(r##"Lists log sinks associated with the specified log."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_logs-sinks-list", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `logName`. The log for which to list sinks."##), + Some(true), + Some(false)), + + (Some(r##"logs-id"##), + None, + Some(r##"Part of `logName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("logs-sinks-update", + Some(r##"Creates or updates the specified log sink resource."##), + "Details at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli/projects_logs-sinks-update", + vec![ + (Some(r##"projects-id"##), + None, + Some(r##"Part of `sinkName`. The name of the sink to update."##), + Some(true), + Some(false)), + + (Some(r##"logs-id"##), + None, + Some(r##"Part of `sinkName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"sinks-id"##), + None, + Some(r##"Part of `sinkName`. See documentation of `projectsId`."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("logging1-beta3") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150326") + .about("Google Cloud Logging API lets you create logs, ingest log entries, and manage log sinks.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_logging1_beta3_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/logging1_beta3/Cargo.toml b/gen/logging1_beta3/Cargo.toml index 5cde36102d..1143f442d8 100644 --- a/gen/logging1_beta3/Cargo.toml +++ b/gen/logging1_beta3/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-logging1_beta3" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with logging (protocol v1beta3)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/logging1_beta3" @@ -14,9 +14,10 @@ keywords = ["logging", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/logging1_beta3/README.md b/gen/logging1_beta3/README.md index 97cfcd6d8a..4473dfc11c 100644 --- a/gen/logging1_beta3/README.md +++ b/gen/logging1_beta3/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-logging1_beta3` library allows access to all features of the *Google logging* service. -This documentation was generated from *logging* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *logging:v1beta3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *logging* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *logging:v1beta3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. # Features Handle the following *Resources* with ease from the central [hub](http://byron.github.io/google-apis-rs/google_logging1_beta3/struct.Logging.html) ... @@ -165,7 +165,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_logging1_beta3/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_logging1_beta3/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/logging1_beta3/src/cmn.rs b/gen/logging1_beta3/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/logging1_beta3/src/cmn.rs +++ b/gen/logging1_beta3/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/logging1_beta3/src/lib.rs b/gen/logging1_beta3/src/lib.rs index fd3fcda196..bfc6c80672 100644 --- a/gen/logging1_beta3/src/lib.rs +++ b/gen/logging1_beta3/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *logging* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *logging:v1beta3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *logging* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *logging:v1beta3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! The original source code is [on github](https://github.com/Byron/google-apis-rs/tree/master/gen/logging1_beta3). //! # Features //! @@ -166,7 +166,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -175,7 +175,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -191,6 +190,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -313,7 +313,7 @@ impl<'a, C, A> Logging<C, A> Logging { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -322,7 +322,7 @@ impl<'a, C, A> Logging<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1129,7 +1129,7 @@ impl<'a, C, A> ProjectLogServiceListCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1151,7 +1151,7 @@ impl<'a, C, A> ProjectLogServiceListCall<'a, C, A> where C: BorrowMut<hyper::Cli access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1413,7 +1413,7 @@ impl<'a, C, A> ProjectLogListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1435,7 +1435,7 @@ impl<'a, C, A> ProjectLogListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1688,7 +1688,7 @@ impl<'a, C, A> ProjectLogSinkGetCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1710,7 +1710,7 @@ impl<'a, C, A> ProjectLogSinkGetCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1905,6 +1905,7 @@ impl<'a, C, A> ProjectLogServiceSinkUpdateCall<'a, C, A> where C: BorrowMut<hype /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LogSink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1962,11 +1963,20 @@ impl<'a, C, A> ProjectLogServiceSinkUpdateCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1989,7 +1999,7 @@ impl<'a, C, A> ProjectLogServiceSinkUpdateCall<'a, C, A> where C: BorrowMut<hype request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2195,6 +2205,7 @@ impl<'a, C, A> ProjectLogEntryWriteCall<'a, C, A> where C: BorrowMut<hyper::Clie /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, WriteLogEntriesResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2251,11 +2262,20 @@ impl<'a, C, A> ProjectLogEntryWriteCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2278,7 +2298,7 @@ impl<'a, C, A> ProjectLogEntryWriteCall<'a, C, A> where C: BorrowMut<hyper::Clie request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2525,7 +2545,7 @@ impl<'a, C, A> ProjectLogServiceSinkDeleteCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2547,7 +2567,7 @@ impl<'a, C, A> ProjectLogServiceSinkDeleteCall<'a, C, A> where C: BorrowMut<hype access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2815,7 +2835,7 @@ impl<'a, C, A> ProjectLogServiceIndexeListCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2837,7 +2857,7 @@ impl<'a, C, A> ProjectLogServiceIndexeListCall<'a, C, A> where C: BorrowMut<hype access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3105,7 +3125,7 @@ impl<'a, C, A> ProjectLogSinkListCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3127,7 +3147,7 @@ impl<'a, C, A> ProjectLogSinkListCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3312,6 +3332,7 @@ impl<'a, C, A> ProjectLogSinkUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clie /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LogSink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3369,11 +3390,20 @@ impl<'a, C, A> ProjectLogSinkUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3396,7 +3426,7 @@ impl<'a, C, A> ProjectLogSinkUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clie request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3602,6 +3632,7 @@ impl<'a, C, A> ProjectLogServiceSinkCreateCall<'a, C, A> where C: BorrowMut<hype /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LogSink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3658,11 +3689,20 @@ impl<'a, C, A> ProjectLogServiceSinkCreateCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3685,7 +3725,7 @@ impl<'a, C, A> ProjectLogServiceSinkCreateCall<'a, C, A> where C: BorrowMut<hype request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3932,7 +3972,7 @@ impl<'a, C, A> ProjectLogSinkDeleteCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3954,7 +3994,7 @@ impl<'a, C, A> ProjectLogSinkDeleteCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4148,6 +4188,7 @@ impl<'a, C, A> ProjectLogSinkCreateCall<'a, C, A> where C: BorrowMut<hyper::Clie /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LogSink)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4204,11 +4245,20 @@ impl<'a, C, A> ProjectLogSinkCreateCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4231,7 +4281,7 @@ impl<'a, C, A> ProjectLogSinkCreateCall<'a, C, A> where C: BorrowMut<hyper::Clie request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4478,7 +4528,7 @@ impl<'a, C, A> ProjectLogServiceSinkGetCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4500,7 +4550,7 @@ impl<'a, C, A> ProjectLogServiceSinkGetCall<'a, C, A> where C: BorrowMut<hyper:: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4743,7 +4793,7 @@ impl<'a, C, A> ProjectLogServiceSinkListCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4765,7 +4815,7 @@ impl<'a, C, A> ProjectLogServiceSinkListCall<'a, C, A> where C: BorrowMut<hyper: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4998,7 +5048,7 @@ impl<'a, C, A> ProjectLogDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5020,7 +5070,7 @@ impl<'a, C, A> ProjectLogDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/manager1_beta2-cli/Cargo.toml b/gen/manager1_beta2-cli/Cargo.toml index 0ae0261cae..dd6f6142be 100644 --- a/gen/manager1_beta2-cli/Cargo.toml +++ b/gen/manager1_beta2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-manager1_beta2-cli" -version = "0.1.0+20140915" +version = "0.2.0+20140915" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with manager (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/manager1_beta2-cli" @@ -17,15 +17,14 @@ keywords = ["manager", "google", "cli"] name = "manager1-beta2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-manager1_beta2] path = "../manager1_beta2" diff --git a/gen/manager1_beta2-cli/README.md b/gen/manager1_beta2-cli/README.md index d46ba0bb72..e2cad060c7 100644 --- a/gen/manager1_beta2-cli/README.md +++ b/gen/manager1_beta2-cli/README.md @@ -10,28 +10,31 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *manager* API can be found at the +[official documentation site](https://developers.google.com/deployment-manager/). + # Usage -This documentation was generated from the *manager* API at revision *20140915*. The CLI is at version *0.1.0*. +This documentation was generated from the *manager* API at revision *20140915*. The CLI is at version *0.2.0*. ```bash - manager1-beta2 [options] deployments delete <project-id> <region> <deployment-name> [-p <v>...] - manager1-beta2 [options] deployments get <project-id> <region> <deployment-name> [-p <v>...] [-o <out>] - manager1-beta2 [options] deployments insert <project-id> <region> -r <kv>... [-p <v>...] [-o <out>] - manager1-beta2 [options] deployments list <project-id> <region> [-p <v>...] [-o <out>] - manager1-beta2 [options] templates delete <project-id> <template-name> [-p <v>...] - manager1-beta2 [options] templates get <project-id> <template-name> [-p <v>...] [-o <out>] - manager1-beta2 [options] templates insert <project-id> -r <kv>... [-p <v>...] [-o <out>] - manager1-beta2 [options] templates list <project-id> [-p <v>...] [-o <out>] +manager1-beta2 [options] + deployments + delete <project-id> <region> <deployment-name> [-p <v>]... + get <project-id> <region> <deployment-name> [-p <v>]... [-o <out>] + insert <project-id> <region> (-r <kv>)... [-p <v>]... [-o <out>] + list <project-id> <region> [-p <v>]... [-o <out>] + templates + delete <project-id> <template-name> [-p <v>]... + get <project-id> <template-name> [-p <v>]... [-o <out>] + insert <project-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <project-id> [-p <v>]... [-o <out>] manager1-beta2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_manager1_beta2_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/manager1_beta2-cli/mkdocs.yml b/gen/manager1_beta2-cli/mkdocs.yml index b44622c309..de5143edd8 100644 --- a/gen/manager1_beta2-cli/mkdocs.yml +++ b/gen/manager1_beta2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: manager v0.1.0+20140915 +site_name: manager v0.2.0+20140915 site_url: http://byron.github.io/google-apis-rs/google-manager1_beta2-cli site_description: Write integrating applications with bcore diff --git a/gen/manager1_beta2-cli/src/cmn.rs b/gen/manager1_beta2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/manager1_beta2-cli/src/cmn.rs +++ b/gen/manager1_beta2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/manager1_beta2-cli/src/main.rs b/gen/manager1_beta2-cli/src/main.rs index d16c71afdc..876b888371 100644 --- a/gen/manager1_beta2-cli/src/main.rs +++ b/gen/manager1_beta2-cli/src/main.rs @@ -2,166 +2,148 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_manager1_beta2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - manager1-beta2 [options] deployments delete <project-id> <region> <deployment-name> [-p <v>...] - manager1-beta2 [options] deployments get <project-id> <region> <deployment-name> [-p <v>...] [-o <out>] - manager1-beta2 [options] deployments insert <project-id> <region> -r <kv>... [-p <v>...] [-o <out>] - manager1-beta2 [options] deployments list <project-id> <region> [-p <v>...] [-o <out>] - manager1-beta2 [options] templates delete <project-id> <template-name> [-p <v>...] - manager1-beta2 [options] templates get <project-id> <template-name> [-p <v>...] [-o <out>] - manager1-beta2 [options] templates insert <project-id> -r <kv>... [-p <v>...] [-o <out>] - manager1-beta2 [options] templates list <project-id> [-p <v>...] [-o <out>] - manager1-beta2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_manager1_beta2_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Manager<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _deployments_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.deployments().delete(&self.opt.arg_project_id, &self.opt.arg_region, &self.opt.arg_deployment_name); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _deployments_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.deployments().delete(opt.value_of("project-id").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("deployment-name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _deployments_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.deployments().get(&self.opt.arg_project_id, &self.opt.arg_region, &self.opt.arg_deployment_name); - for parg in self.opt.arg_v.iter() { + fn _deployments_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.deployments().get(opt.value_of("project-id").unwrap_or(""), opt.value_of("region").unwrap_or(""), opt.value_of("deployment-name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _deployments_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _deployments_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Deployment::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -207,58 +189,63 @@ impl Engine { request.template_name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-date", "description", "details", "name", "state", "status", "template-name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.deployments().insert(request, &self.opt.arg_project_id, &self.opt.arg_region); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.deployments().insert(request, opt.value_of("project-id").unwrap_or(""), opt.value_of("region").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _deployments_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.deployments().list(&self.opt.arg_project_id, &self.opt.arg_region); - for parg in self.opt.arg_v.iter() { + fn _deployments_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.deployments().list(opt.value_of("project-id").unwrap_or(""), opt.value_of("region").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -267,142 +254,149 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _templates_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.templates().delete(&self.opt.arg_project_id, &self.opt.arg_template_name); - for parg in self.opt.arg_v.iter() { + fn _templates_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.templates().delete(opt.value_of("project-id").unwrap_or(""), opt.value_of("template-name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _templates_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.templates().get(&self.opt.arg_project_id, &self.opt.arg_template_name); - for parg in self.opt.arg_v.iter() { + fn _templates_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.templates().get(opt.value_of("project-id").unwrap_or(""), opt.value_of("template-name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _templates_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _templates_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Template::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -424,58 +418,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["description", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.templates().insert(request, &self.opt.arg_project_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.templates().insert(request, opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _templates_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.templates().list(&self.opt.arg_project_id); - for parg in self.opt.arg_v.iter() { + fn _templates_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.templates().list(opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -484,92 +483,115 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_deployments { - if self.opt.cmd_delete { - call_result = self._deployments_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._deployments_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._deployments_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._deployments_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("deployments", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._deployments_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._deployments_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._deployments_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._deployments_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("deployments".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("templates", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._templates_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._templates_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._templates_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._templates_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("templates".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_templates { - if self.opt.cmd_delete { - call_result = self._templates_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._templates_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._templates_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._templates_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -582,7 +604,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -595,7 +617,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -605,37 +627,353 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Manager::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("deployments", "methods: 'delete', 'get', 'insert' and 'list'", vec![ + ("delete", + Some(r##""##), + "Details at http://byron.github.io/google-apis-rs/google_manager1_beta2_cli/deployments_delete", + vec![ + (Some(r##"project-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"deployment-name"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##""##), + "Details at http://byron.github.io/google-apis-rs/google_manager1_beta2_cli/deployments_get", + vec![ + (Some(r##"project-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"deployment-name"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##""##), + "Details at http://byron.github.io/google-apis-rs/google_manager1_beta2_cli/deployments_insert", + vec![ + (Some(r##"project-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##""##), + "Details at http://byron.github.io/google-apis-rs/google_manager1_beta2_cli/deployments_list", + vec![ + (Some(r##"project-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"region"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("templates", "methods: 'delete', 'get', 'insert' and 'list'", vec![ + ("delete", + Some(r##""##), + "Details at http://byron.github.io/google-apis-rs/google_manager1_beta2_cli/templates_delete", + vec![ + (Some(r##"project-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"template-name"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##""##), + "Details at http://byron.github.io/google-apis-rs/google_manager1_beta2_cli/templates_get", + vec![ + (Some(r##"project-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"template-name"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##""##), + "Details at http://byron.github.io/google-apis-rs/google_manager1_beta2_cli/templates_insert", + vec![ + (Some(r##"project-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##""##), + "Details at http://byron.github.io/google-apis-rs/google_manager1_beta2_cli/templates_list", + vec![ + (Some(r##"project-id"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("manager1-beta2") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20140915") + .about("The Deployment Manager API allows users to declaratively configure, deploy and run complex solutions on the Google Cloud Platform.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_manager1_beta2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/manager1_beta2/Cargo.toml b/gen/manager1_beta2/Cargo.toml index c743a90c03..ccfb3a597b 100644 --- a/gen/manager1_beta2/Cargo.toml +++ b/gen/manager1_beta2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-manager1_beta2" -version = "0.1.6+20140915" +version = "0.1.7+20140915" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with manager (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/manager1_beta2" @@ -15,9 +15,10 @@ keywords = ["manager", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/manager1_beta2/README.md b/gen/manager1_beta2/README.md index 2c3689757b..09c7e9fc34 100644 --- a/gen/manager1_beta2/README.md +++ b/gen/manager1_beta2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-manager1_beta2` library allows access to all features of the *Google manager* service. -This documentation was generated from *manager* crate version *0.1.6+20140915*, where *20140915* is the exact revision of the *manager:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *manager* crate version *0.1.7+20140915*, where *20140915* is the exact revision of the *manager:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *manager* *v1_beta2* API can be found at the [official documentation site](https://developers.google.com/deployment-manager/). @@ -164,7 +164,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_manager1_beta2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_manager1_beta2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/manager1_beta2/src/cmn.rs b/gen/manager1_beta2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/manager1_beta2/src/cmn.rs +++ b/gen/manager1_beta2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/manager1_beta2/src/lib.rs b/gen/manager1_beta2/src/lib.rs index bc174d4f81..247b8a3a9e 100644 --- a/gen/manager1_beta2/src/lib.rs +++ b/gen/manager1_beta2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *manager* crate version *0.1.6+20140915*, where *20140915* is the exact revision of the *manager:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *manager* crate version *0.1.7+20140915*, where *20140915* is the exact revision of the *manager:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *manager* *v1_beta2* API can be found at the //! [official documentation site](https://developers.google.com/deployment-manager/). @@ -165,7 +165,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -174,7 +174,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -190,6 +189,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -328,7 +328,7 @@ impl<'a, C, A> Manager<C, A> Manager { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -340,7 +340,7 @@ impl<'a, C, A> Manager<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1467,7 +1467,7 @@ impl<'a, C, A> TemplateListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1489,7 +1489,7 @@ impl<'a, C, A> TemplateListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1720,7 +1720,7 @@ impl<'a, C, A> TemplateDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1742,7 +1742,7 @@ impl<'a, C, A> TemplateDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1909,6 +1909,7 @@ impl<'a, C, A> TemplateInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Template)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1964,11 +1965,20 @@ impl<'a, C, A> TemplateInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1991,7 +2001,7 @@ impl<'a, C, A> TemplateInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2221,7 +2231,7 @@ impl<'a, C, A> TemplateGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2243,7 +2253,7 @@ impl<'a, C, A> TemplateGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2421,6 +2431,7 @@ impl<'a, C, A> DeploymentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Deployment)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2477,11 +2488,20 @@ impl<'a, C, A> DeploymentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2504,7 +2524,7 @@ impl<'a, C, A> DeploymentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2745,7 +2765,7 @@ impl<'a, C, A> DeploymentGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2767,7 +2787,7 @@ impl<'a, C, A> DeploymentGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3013,7 +3033,7 @@ impl<'a, C, A> DeploymentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3035,7 +3055,7 @@ impl<'a, C, A> DeploymentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3277,7 +3297,7 @@ impl<'a, C, A> DeploymentDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3299,7 +3319,7 @@ impl<'a, C, A> DeploymentDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/mapsengine1-cli/Cargo.toml b/gen/mapsengine1-cli/Cargo.toml index 5fc0b620be..f2ded12885 100644 --- a/gen/mapsengine1-cli/Cargo.toml +++ b/gen/mapsengine1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-mapsengine1-cli" -version = "0.1.0+20150414" +version = "0.2.0+20150414" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with Maps Engine (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/mapsengine1-cli" @@ -17,15 +17,14 @@ keywords = ["mapsengine", "google", "cli"] name = "mapsengine1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-mapsengine1] path = "../mapsengine1" diff --git a/gen/mapsengine1-cli/README.md b/gen/mapsengine1-cli/README.md index d20bd018c2..e06cb4d427 100644 --- a/gen/mapsengine1-cli/README.md +++ b/gen/mapsengine1-cli/README.md @@ -10,97 +10,105 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *Maps Engine* API can be found at the +[official documentation site](https://developers.google.com/maps-engine/). + # Usage -This documentation was generated from the *Maps Engine* API at revision *20150414*. The CLI is at version *0.1.0*. +This documentation was generated from the *Maps Engine* API at revision *20150414*. The CLI is at version *0.2.0*. ```bash - mapsengine1 [options] assets get <id> [-p <v>...] [-o <out>] - mapsengine1 [options] assets list [-p <v>...] [-o <out>] - mapsengine1 [options] assets parents-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] assets permissions-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers cancel-processing <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers create -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] layers delete <id> [-p <v>...] - mapsengine1 [options] layers get <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers get-published <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers list [-p <v>...] [-o <out>] - mapsengine1 [options] layers list-published [-p <v>...] [-o <out>] - mapsengine1 [options] layers parents-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers patch <id> -r <kv>... [-p <v>...] - mapsengine1 [options] layers permissions-batch-delete <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] layers permissions-batch-update <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] layers permissions-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers process <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers publish <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers unpublish <id> [-p <v>...] [-o <out>] - mapsengine1 [options] maps create -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] maps delete <id> [-p <v>...] - mapsengine1 [options] maps get <id> [-p <v>...] [-o <out>] - mapsengine1 [options] maps get-published <id> [-p <v>...] [-o <out>] - mapsengine1 [options] maps list [-p <v>...] [-o <out>] - mapsengine1 [options] maps list-published [-p <v>...] [-o <out>] - mapsengine1 [options] maps patch <id> -r <kv>... [-p <v>...] - mapsengine1 [options] maps permissions-batch-delete <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] maps permissions-batch-update <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] maps permissions-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] maps publish <id> [-p <v>...] [-o <out>] - mapsengine1 [options] maps unpublish <id> [-p <v>...] [-o <out>] - mapsengine1 [options] projects icons-create <project-id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - mapsengine1 [options] projects icons-get <project-id> <id> [-p <v>...] [-o <out>] - mapsengine1 [options] projects icons-list <project-id> [-p <v>...] [-o <out>] - mapsengine1 [options] projects list [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections cancel-processing <id> [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections create -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections delete <id> [-p <v>...] - mapsengine1 [options] raster-collections get <id> [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections list [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections parents-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections patch <id> -r <kv>... [-p <v>...] - mapsengine1 [options] raster-collections permissions-batch-delete <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections permissions-batch-update <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections permissions-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections process <id> [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections rasters-batch-delete <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections rasters-batch-insert <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections rasters-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] rasters delete <id> [-p <v>...] - mapsengine1 [options] rasters files-insert <id> <filename> -u (simple|resumable) <file> <mime> [-p <v>...] - mapsengine1 [options] rasters get <id> [-p <v>...] [-o <out>] - mapsengine1 [options] rasters list <project-id> [-p <v>...] [-o <out>] - mapsengine1 [options] rasters parents-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] rasters patch <id> -r <kv>... [-p <v>...] - mapsengine1 [options] rasters permissions-batch-delete <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] rasters permissions-batch-update <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] rasters permissions-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] rasters process <id> [-p <v>...] [-o <out>] - mapsengine1 [options] rasters upload -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] tables create -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] tables delete <id> [-p <v>...] - mapsengine1 [options] tables features-batch-delete <id> -r <kv>... [-p <v>...] - mapsengine1 [options] tables features-batch-insert <id> -r <kv>... [-p <v>...] - mapsengine1 [options] tables features-batch-patch <id> -r <kv>... [-p <v>...] - mapsengine1 [options] tables features-get <table-id> <id> [-p <v>...] [-o <out>] - mapsengine1 [options] tables features-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] tables files-insert <id> <filename> -u (simple|resumable) <file> <mime> [-p <v>...] - mapsengine1 [options] tables get <id> [-p <v>...] [-o <out>] - mapsengine1 [options] tables list [-p <v>...] [-o <out>] - mapsengine1 [options] tables parents-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] tables patch <id> -r <kv>... [-p <v>...] - mapsengine1 [options] tables permissions-batch-delete <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] tables permissions-batch-update <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] tables permissions-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] tables process <id> [-p <v>...] [-o <out>] - mapsengine1 [options] tables upload -r <kv>... [-p <v>...] [-o <out>] +mapsengine1 [options] + assets + get <id> [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + parents-list <id> [-p <v>]... [-o <out>] + permissions-list <id> [-p <v>]... [-o <out>] + layers + cancel-processing <id> [-p <v>]... [-o <out>] + create (-r <kv>)... [-p <v>]... [-o <out>] + delete <id> [-p <v>]... + get <id> [-p <v>]... [-o <out>] + get-published <id> [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + list-published [-p <v>]... [-o <out>] + parents-list <id> [-p <v>]... [-o <out>] + patch <id> (-r <kv>)... [-p <v>]... + permissions-batch-delete <id> (-r <kv>)... [-p <v>]... [-o <out>] + permissions-batch-update <id> (-r <kv>)... [-p <v>]... [-o <out>] + permissions-list <id> [-p <v>]... [-o <out>] + process <id> [-p <v>]... [-o <out>] + publish <id> [-p <v>]... [-o <out>] + unpublish <id> [-p <v>]... [-o <out>] + maps + create (-r <kv>)... [-p <v>]... [-o <out>] + delete <id> [-p <v>]... + get <id> [-p <v>]... [-o <out>] + get-published <id> [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + list-published [-p <v>]... [-o <out>] + patch <id> (-r <kv>)... [-p <v>]... + permissions-batch-delete <id> (-r <kv>)... [-p <v>]... [-o <out>] + permissions-batch-update <id> (-r <kv>)... [-p <v>]... [-o <out>] + permissions-list <id> [-p <v>]... [-o <out>] + publish <id> [-p <v>]... [-o <out>] + unpublish <id> [-p <v>]... [-o <out>] + projects + icons-create <project-id> (-r <kv>)... (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + icons-get <project-id> <id> [-p <v>]... [-o <out>] + icons-list <project-id> [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + raster-collections + cancel-processing <id> [-p <v>]... [-o <out>] + create (-r <kv>)... [-p <v>]... [-o <out>] + delete <id> [-p <v>]... + get <id> [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + parents-list <id> [-p <v>]... [-o <out>] + patch <id> (-r <kv>)... [-p <v>]... + permissions-batch-delete <id> (-r <kv>)... [-p <v>]... [-o <out>] + permissions-batch-update <id> (-r <kv>)... [-p <v>]... [-o <out>] + permissions-list <id> [-p <v>]... [-o <out>] + process <id> [-p <v>]... [-o <out>] + rasters-batch-delete <id> (-r <kv>)... [-p <v>]... [-o <out>] + rasters-batch-insert <id> (-r <kv>)... [-p <v>]... [-o <out>] + rasters-list <id> [-p <v>]... [-o <out>] + rasters + delete <id> [-p <v>]... + files-insert <id> <filename> (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... + get <id> [-p <v>]... [-o <out>] + list <project-id> [-p <v>]... [-o <out>] + parents-list <id> [-p <v>]... [-o <out>] + patch <id> (-r <kv>)... [-p <v>]... + permissions-batch-delete <id> (-r <kv>)... [-p <v>]... [-o <out>] + permissions-batch-update <id> (-r <kv>)... [-p <v>]... [-o <out>] + permissions-list <id> [-p <v>]... [-o <out>] + process <id> [-p <v>]... [-o <out>] + upload (-r <kv>)... [-p <v>]... [-o <out>] + tables + create (-r <kv>)... [-p <v>]... [-o <out>] + delete <id> [-p <v>]... + features-batch-delete <id> (-r <kv>)... [-p <v>]... + features-batch-insert <id> (-r <kv>)... [-p <v>]... + features-batch-patch <id> (-r <kv>)... [-p <v>]... + features-get <table-id> <id> [-p <v>]... [-o <out>] + features-list <id> [-p <v>]... [-o <out>] + files-insert <id> <filename> (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... + get <id> [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + parents-list <id> [-p <v>]... [-o <out>] + patch <id> (-r <kv>)... [-p <v>]... + permissions-batch-delete <id> (-r <kv>)... [-p <v>]... [-o <out>] + permissions-batch-update <id> (-r <kv>)... [-p <v>]... [-o <out>] + permissions-list <id> [-p <v>]... [-o <out>] + process <id> [-p <v>]... [-o <out>] + upload (-r <kv>)... [-p <v>]... [-o <out>] mapsengine1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_mapsengine1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/mapsengine1-cli/mkdocs.yml b/gen/mapsengine1-cli/mkdocs.yml index 35438dfabd..79c8ff0cc5 100644 --- a/gen/mapsengine1-cli/mkdocs.yml +++ b/gen/mapsengine1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Maps Engine v0.1.0+20150414 +site_name: Maps Engine v0.2.0+20150414 site_url: http://byron.github.io/google-apis-rs/google-mapsengine1-cli site_description: Write integrating applications with bcore diff --git a/gen/mapsengine1-cli/src/cmn.rs b/gen/mapsengine1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/mapsengine1-cli/src/cmn.rs +++ b/gen/mapsengine1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/mapsengine1-cli/src/main.rs b/gen/mapsengine1-cli/src/main.rs index f2318a27b2..359729b1fc 100644 --- a/gen/mapsengine1-cli/src/main.rs +++ b/gen/mapsengine1-cli/src/main.rs @@ -2,189 +2,103 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_mapsengine1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - mapsengine1 [options] assets get <id> [-p <v>...] [-o <out>] - mapsengine1 [options] assets list [-p <v>...] [-o <out>] - mapsengine1 [options] assets parents-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] assets permissions-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers cancel-processing <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers create -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] layers delete <id> [-p <v>...] - mapsengine1 [options] layers get <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers get-published <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers list [-p <v>...] [-o <out>] - mapsengine1 [options] layers list-published [-p <v>...] [-o <out>] - mapsengine1 [options] layers parents-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers patch <id> -r <kv>... [-p <v>...] - mapsengine1 [options] layers permissions-batch-delete <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] layers permissions-batch-update <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] layers permissions-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers process <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers publish <id> [-p <v>...] [-o <out>] - mapsengine1 [options] layers unpublish <id> [-p <v>...] [-o <out>] - mapsengine1 [options] maps create -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] maps delete <id> [-p <v>...] - mapsengine1 [options] maps get <id> [-p <v>...] [-o <out>] - mapsengine1 [options] maps get-published <id> [-p <v>...] [-o <out>] - mapsengine1 [options] maps list [-p <v>...] [-o <out>] - mapsengine1 [options] maps list-published [-p <v>...] [-o <out>] - mapsengine1 [options] maps patch <id> -r <kv>... [-p <v>...] - mapsengine1 [options] maps permissions-batch-delete <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] maps permissions-batch-update <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] maps permissions-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] maps publish <id> [-p <v>...] [-o <out>] - mapsengine1 [options] maps unpublish <id> [-p <v>...] [-o <out>] - mapsengine1 [options] projects icons-create <project-id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - mapsengine1 [options] projects icons-get <project-id> <id> [-p <v>...] [-o <out>] - mapsengine1 [options] projects icons-list <project-id> [-p <v>...] [-o <out>] - mapsengine1 [options] projects list [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections cancel-processing <id> [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections create -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections delete <id> [-p <v>...] - mapsengine1 [options] raster-collections get <id> [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections list [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections parents-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections patch <id> -r <kv>... [-p <v>...] - mapsengine1 [options] raster-collections permissions-batch-delete <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections permissions-batch-update <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections permissions-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections process <id> [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections rasters-batch-delete <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections rasters-batch-insert <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] raster-collections rasters-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] rasters delete <id> [-p <v>...] - mapsengine1 [options] rasters files-insert <id> <filename> -u (simple|resumable) <file> <mime> [-p <v>...] - mapsengine1 [options] rasters get <id> [-p <v>...] [-o <out>] - mapsengine1 [options] rasters list <project-id> [-p <v>...] [-o <out>] - mapsengine1 [options] rasters parents-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] rasters patch <id> -r <kv>... [-p <v>...] - mapsengine1 [options] rasters permissions-batch-delete <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] rasters permissions-batch-update <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] rasters permissions-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] rasters process <id> [-p <v>...] [-o <out>] - mapsengine1 [options] rasters upload -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] tables create -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] tables delete <id> [-p <v>...] - mapsengine1 [options] tables features-batch-delete <id> -r <kv>... [-p <v>...] - mapsengine1 [options] tables features-batch-insert <id> -r <kv>... [-p <v>...] - mapsengine1 [options] tables features-batch-patch <id> -r <kv>... [-p <v>...] - mapsengine1 [options] tables features-get <table-id> <id> [-p <v>...] [-o <out>] - mapsengine1 [options] tables features-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] tables files-insert <id> <filename> -u (simple|resumable) <file> <mime> [-p <v>...] - mapsengine1 [options] tables get <id> [-p <v>...] [-o <out>] - mapsengine1 [options] tables list [-p <v>...] [-o <out>] - mapsengine1 [options] tables parents-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] tables patch <id> -r <kv>... [-p <v>...] - mapsengine1 [options] tables permissions-batch-delete <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] tables permissions-batch-update <id> -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 [options] tables permissions-list <id> [-p <v>...] [-o <out>] - mapsengine1 [options] tables process <id> [-p <v>...] [-o <out>] - mapsengine1 [options] tables upload -r <kv>... [-p <v>...] [-o <out>] - mapsengine1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_mapsengine1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::MapsEngine<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _assets_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.assets().get(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _assets_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.assets().get(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _assets_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _assets_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.assets().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "type" => { @@ -226,50 +140,54 @@ impl Engine { "bbox" => { call = call.bbox(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["modified-after", "search", "tags", "project-id", "created-after", "max-results", "page-token", "created-before", "role", "bbox", "modified-before", "creator-email", "type"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _assets_parents_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.assets().parents_list(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _assets_parents_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.assets().parents_list(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -278,144 +196,156 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _assets_permissions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.assets().permissions_list(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _assets_permissions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.assets().permissions_list(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_cancel_processing(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.layers().cancel_processing(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _layers_cancel_processing(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().cancel_processing(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _layers_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Layer::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -523,200 +453,212 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bbox", "content", "creation-time", "creator-email", "datasource-type", "description", "draft-access-list", "etag", "feature-info", "id", "last-modified-time", "last-modifier-email", "layer-type", "name", "processing-status", "project-id", "published-access-list", "publishing-status", "style", "type", "writers-can-edit-permissions"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.layers().create(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "process" => { call = call.process(arg_from_str(value.unwrap_or("false"), err, "process", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["process"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.layers().delete(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _layers_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().delete(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _layers_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.layers().get(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _layers_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().get(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "version" => { call = call.version(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["version"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_get_published(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.layers().get_published(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _layers_get_published(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().get_published(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _layers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.layers().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "tags" => { @@ -758,50 +700,54 @@ impl Engine { "bbox" => { call = call.bbox(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["modified-after", "search", "processing-status", "project-id", "tags", "created-after", "max-results", "page-token", "created-before", "role", "bbox", "modified-before", "creator-email"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_list_published(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _layers_list_published(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.layers().list_published(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "project-id" => { @@ -813,50 +759,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["project-id", "max-results", "page-token"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_parents_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.layers().parents_list(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _layers_parents_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().parents_list(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -865,52 +815,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _layers_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Layer::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1018,58 +972,58 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bbox", "content", "creation-time", "creator-email", "datasource-type", "description", "draft-access-list", "etag", "feature-info", "id", "last-modified-time", "last-modifier-email", "layer-type", "name", "processing-status", "project-id", "published-access-list", "publishing-status", "style", "type", "writers-can-edit-permissions"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.layers().patch(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.layers().patch(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _layers_permissions_batch_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _layers_permissions_batch_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PermissionsBatchDeleteRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1091,60 +1045,65 @@ impl Engine { request.ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.layers().permissions_batch_delete(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.layers().permissions_batch_delete(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_permissions_batch_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _layers_permissions_batch_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PermissionsBatchUpdateRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1160,247 +1119,268 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.layers().permissions_batch_update(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.layers().permissions_batch_update(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_permissions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.layers().permissions_list(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _layers_permissions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().permissions_list(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_process(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.layers().process(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _layers_process(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().process(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_publish(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.layers().publish(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _layers_publish(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().publish(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "force" => { call = call.force(arg_from_str(value.unwrap_or("false"), err, "force", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["force"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _layers_unpublish(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.layers().unpublish(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _layers_unpublish(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.layers().unpublish(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _maps_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _maps_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Map::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1470,197 +1450,209 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bbox", "creation-time", "creator-email", "description", "draft-access-list", "etag", "id", "last-modified-time", "last-modifier-email", "name", "processing-status", "project-id", "published-access-list", "publishing-status", "versions", "writers-can-edit-permissions"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.maps().create(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _maps_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.maps().delete(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _maps_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.maps().delete(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _maps_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.maps().get(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _maps_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.maps().get(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "version" => { call = call.version(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["version"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _maps_get_published(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.maps().get_published(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _maps_get_published(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.maps().get_published(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _maps_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _maps_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.maps().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "tags" => { @@ -1702,50 +1694,54 @@ impl Engine { "bbox" => { call = call.bbox(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["modified-after", "search", "processing-status", "project-id", "tags", "created-after", "max-results", "page-token", "created-before", "role", "bbox", "modified-before", "creator-email"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _maps_list_published(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _maps_list_published(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.maps().list_published(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "project-id" => { @@ -1757,52 +1753,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["project-id", "max-results", "page-token"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _maps_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _maps_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Map::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1872,58 +1872,58 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bbox", "creation-time", "creator-email", "description", "draft-access-list", "etag", "id", "last-modified-time", "last-modifier-email", "name", "processing-status", "project-id", "published-access-list", "publishing-status", "versions", "writers-can-edit-permissions"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.maps().patch(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.maps().patch(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _maps_permissions_batch_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _maps_permissions_batch_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PermissionsBatchDeleteRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1945,60 +1945,65 @@ impl Engine { request.ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.maps().permissions_batch_delete(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.maps().permissions_batch_delete(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _maps_permissions_batch_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _maps_permissions_batch_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PermissionsBatchUpdateRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2014,201 +2019,218 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.maps().permissions_batch_update(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.maps().permissions_batch_update(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _maps_permissions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.maps().permissions_list(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _maps_permissions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.maps().permissions_list(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _maps_publish(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.maps().publish(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _maps_publish(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.maps().publish(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "force" => { call = call.force(arg_from_str(value.unwrap_or("false"), err, "force", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["force"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _maps_unpublish(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.maps().unpublish(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _maps_unpublish(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.maps().unpublish(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_icons_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _projects_icons_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Icon::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2233,122 +2255,125 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["description", "id", "name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().icons_create(request, &self.opt.arg_project_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().icons_create(request, opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() - }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_icons_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _projects_icons_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut download_mode = false; - let mut call = self.hub.projects().icons_get(&self.opt.arg_project_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().icons_get(opt.value_of("project-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { if !download_mode { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); } else { io::copy(&mut response, &mut ostream).unwrap(); } - None + Ok(()) } } } } - fn _projects_icons_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().icons_list(&self.opt.arg_project_id); - for parg in self.opt.arg_v.iter() { + fn _projects_icons_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().icons_list(opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2357,144 +2382,156 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _projects_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.projects().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _raster_collections_cancel_processing(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.raster_collections().cancel_processing(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _raster_collections_cancel_processing(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.raster_collections().cancel_processing(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _raster_collections_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _raster_collections_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::RasterCollection::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2561,148 +2598,156 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attribution", "bbox", "creation-time", "creator-email", "description", "draft-access-list", "etag", "id", "last-modified-time", "last-modifier-email", "mosaic", "name", "processing-status", "project-id", "raster-type", "writers-can-edit-permissions"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.raster_collections().create(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _raster_collections_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.raster_collections().delete(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _raster_collections_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.raster_collections().delete(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _raster_collections_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.raster_collections().get(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _raster_collections_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.raster_collections().get(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _raster_collections_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _raster_collections_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.raster_collections().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "tags" => { @@ -2744,50 +2789,54 @@ impl Engine { "bbox" => { call = call.bbox(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["modified-after", "search", "processing-status", "project-id", "tags", "created-after", "max-results", "page-token", "created-before", "role", "bbox", "modified-before", "creator-email"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _raster_collections_parents_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.raster_collections().parents_list(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _raster_collections_parents_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.raster_collections().parents_list(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2796,52 +2845,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _raster_collections_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _raster_collections_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::RasterCollection::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2908,58 +2961,58 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attribution", "bbox", "creation-time", "creator-email", "description", "draft-access-list", "etag", "id", "last-modified-time", "last-modifier-email", "mosaic", "name", "processing-status", "project-id", "raster-type", "writers-can-edit-permissions"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.raster_collections().patch(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.raster_collections().patch(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _raster_collections_permissions_batch_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _raster_collections_permissions_batch_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PermissionsBatchDeleteRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2981,60 +3034,65 @@ impl Engine { request.ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.raster_collections().permissions_batch_delete(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.raster_collections().permissions_batch_delete(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _raster_collections_permissions_batch_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _raster_collections_permissions_batch_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PermissionsBatchUpdateRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3050,152 +3108,165 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.raster_collections().permissions_batch_update(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.raster_collections().permissions_batch_update(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _raster_collections_permissions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.raster_collections().permissions_list(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _raster_collections_permissions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.raster_collections().permissions_list(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _raster_collections_process(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.raster_collections().process(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _raster_collections_process(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.raster_collections().process(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _raster_collections_rasters_batch_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _raster_collections_rasters_batch_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::RasterCollectionsRasterBatchDeleteRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3217,60 +3288,65 @@ impl Engine { request.ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.raster_collections().rasters_batch_delete(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.raster_collections().rasters_batch_delete(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _raster_collections_rasters_batch_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _raster_collections_rasters_batch_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::RasterCollectionsRastersBatchInsertRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3292,58 +3368,63 @@ impl Engine { request.ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.raster_collections().rasters_batch_insert(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.raster_collections().rasters_batch_insert(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _raster_collections_rasters_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.raster_collections().rasters_list(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _raster_collections_rasters_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.raster_collections().rasters_list(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "tags" => { @@ -3379,194 +3460,194 @@ impl Engine { "bbox" => { call = call.bbox(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["modified-after", "search", "tags", "created-after", "max-results", "page-token", "created-before", "role", "bbox", "modified-before", "creator-email"] + )); + } } } } - } - - fn _rasters_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rasters().delete(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok(mut response) => { - None - } - } - } - } - - fn _rasters_files_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rasters().files_insert(&self.opt.arg_id, &self.opt.arg_filename); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), - Ok(mut response) => { - None + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rasters_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rasters().get(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _rasters_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rasters().delete(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) } } } } - fn _rasters_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rasters().list(&self.opt.arg_project_id); - for parg in self.opt.arg_v.iter() { + fn _rasters_files_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rasters().files_insert(opt.value_of("id").unwrap_or(""), opt.value_of("filename").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _rasters_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rasters().get(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _rasters_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rasters().list(opt.value_of("project-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "tags" => { @@ -3605,50 +3686,54 @@ impl Engine { "bbox" => { call = call.bbox(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["modified-after", "search", "processing-status", "tags", "created-after", "max-results", "page-token", "created-before", "role", "bbox", "modified-before", "creator-email"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rasters_parents_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rasters().parents_list(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _rasters_parents_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rasters().parents_list(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -3657,52 +3742,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rasters_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _rasters_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Raster::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3803,58 +3892,58 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["acquisition-time", "attribution", "bbox", "creation-time", "creator-email", "description", "draft-access-list", "end", "etag", "id", "last-modified-time", "last-modifier-email", "mask-type", "name", "precision", "processing-status", "project-id", "raster-type", "start", "writers-can-edit-permissions"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.rasters().patch(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.rasters().patch(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _rasters_permissions_batch_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _rasters_permissions_batch_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PermissionsBatchDeleteRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3876,60 +3965,65 @@ impl Engine { request.ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.rasters().permissions_batch_delete(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.rasters().permissions_batch_delete(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rasters_permissions_batch_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _rasters_permissions_batch_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PermissionsBatchUpdateRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3945,152 +4039,165 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.rasters().permissions_batch_update(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.rasters().permissions_batch_update(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rasters_permissions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rasters().permissions_list(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _rasters_permissions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rasters().permissions_list(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rasters_process(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rasters().process(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _rasters_process(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rasters().process(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rasters_upload(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _rasters_upload(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Raster::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4191,60 +4298,65 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["acquisition-time", "attribution", "bbox", "creation-time", "creator-email", "description", "draft-access-list", "end", "etag", "id", "last-modified-time", "last-modifier-email", "mask-type", "name", "precision", "processing-status", "project-id", "raster-type", "start", "writers-can-edit-permissions"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.rasters().upload(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tables_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Table::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4337,104 +4449,108 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bbox", "creation-time", "creator-email", "description", "draft-access-list", "etag", "id", "last-modified-time", "last-modifier-email", "name", "primary-geometry", "primary-key", "processing-status", "project-id", "published-access-list", "schema", "source-encoding", "writers-can-edit-permissions"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.tables().create(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tables().delete(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _tables_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tables().delete(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _tables_features_batch_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tables_features_batch_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::FeaturesBatchDeleteRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4462,58 +4578,58 @@ impl Engine { request.primary_keys.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["gx-ids", "primary-keys"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tables().features_batch_delete(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tables().features_batch_delete(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _tables_features_batch_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tables_features_batch_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::FeaturesBatchInsertRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4532,58 +4648,58 @@ impl Engine { request.normalize_geometries = Some(arg_from_str(value.unwrap_or("false"), err, "normalize-geometries", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["normalize-geometries"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tables().features_batch_insert(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tables().features_batch_insert(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _tables_features_batch_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tables_features_batch_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::FeaturesBatchPatchRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -4602,56 +4718,56 @@ impl Engine { request.normalize_geometries = Some(arg_from_str(value.unwrap_or("false"), err, "normalize-geometries", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["normalize-geometries"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tables().features_batch_patch(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tables().features_batch_patch(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _tables_features_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tables().features_get(&self.opt.arg_table_id, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _tables_features_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tables().features_get(opt.value_of("table-id").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "version" => { @@ -4660,50 +4776,54 @@ impl Engine { "select" => { call = call.select(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["version", "select"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_features_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tables().features_list(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _tables_features_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tables().features_list(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "where" => { @@ -4733,153 +4853,154 @@ impl Engine { "include" => { call = call.include(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["order-by", "intersects", "max-results", "page-token", "version", "limit", "include", "where", "select"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_files_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tables().files_insert(&self.opt.arg_id, &self.opt.arg_filename); - for parg in self.opt.arg_v.iter() { + fn _tables_files_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tables().files_insert(opt.value_of("id").unwrap_or(""), opt.value_of("filename").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() - }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _tables_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tables().get(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _tables_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tables().get(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "version" => { call = call.version(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["version"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tables_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.tables().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "tags" => { @@ -4921,50 +5042,54 @@ impl Engine { "bbox" => { call = call.bbox(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["modified-after", "search", "processing-status", "project-id", "tags", "created-after", "max-results", "page-token", "created-before", "role", "bbox", "modified-before", "creator-email"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_parents_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tables().parents_list(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _tables_parents_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tables().parents_list(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -4973,52 +5098,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tables_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Table::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -5111,58 +5240,58 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bbox", "creation-time", "creator-email", "description", "draft-access-list", "etag", "id", "last-modified-time", "last-modifier-email", "name", "primary-geometry", "primary-key", "processing-status", "project-id", "published-access-list", "schema", "source-encoding", "writers-can-edit-permissions"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tables().patch(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tables().patch(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _tables_permissions_batch_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tables_permissions_batch_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PermissionsBatchDeleteRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -5184,60 +5313,65 @@ impl Engine { request.ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tables().permissions_batch_delete(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tables().permissions_batch_delete(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_permissions_batch_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tables_permissions_batch_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PermissionsBatchUpdateRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -5253,152 +5387,165 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tables().permissions_batch_update(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tables().permissions_batch_update(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_permissions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tables().permissions_list(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _tables_permissions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tables().permissions_list(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_process(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tables().process(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _tables_process(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tables().process(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tables_upload(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tables_upload(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Table::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -5491,263 +5638,371 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bbox", "creation-time", "creator-email", "description", "draft-access-list", "etag", "id", "last-modified-time", "last-modifier-email", "name", "primary-geometry", "primary-key", "processing-status", "project-id", "published-access-list", "schema", "source-encoding", "writers-can-edit-permissions"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.tables().upload(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_assets { - if self.opt.cmd_get { - call_result = self._assets_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._assets_list(dry_run, &mut err); - } else if self.opt.cmd_parents_list { - call_result = self._assets_parents_list(dry_run, &mut err); - } else if self.opt.cmd_permissions_list { - call_result = self._assets_permissions_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("assets", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._assets_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._assets_list(opt, dry_run, &mut err); + }, + ("parents-list", Some(opt)) => { + call_result = self._assets_parents_list(opt, dry_run, &mut err); + }, + ("permissions-list", Some(opt)) => { + call_result = self._assets_permissions_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("assets".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("layers", Some(opt)) => { + match opt.subcommand() { + ("cancel-processing", Some(opt)) => { + call_result = self._layers_cancel_processing(opt, dry_run, &mut err); + }, + ("create", Some(opt)) => { + call_result = self._layers_create(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._layers_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._layers_get(opt, dry_run, &mut err); + }, + ("get-published", Some(opt)) => { + call_result = self._layers_get_published(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._layers_list(opt, dry_run, &mut err); + }, + ("list-published", Some(opt)) => { + call_result = self._layers_list_published(opt, dry_run, &mut err); + }, + ("parents-list", Some(opt)) => { + call_result = self._layers_parents_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._layers_patch(opt, dry_run, &mut err); + }, + ("permissions-batch-delete", Some(opt)) => { + call_result = self._layers_permissions_batch_delete(opt, dry_run, &mut err); + }, + ("permissions-batch-update", Some(opt)) => { + call_result = self._layers_permissions_batch_update(opt, dry_run, &mut err); + }, + ("permissions-list", Some(opt)) => { + call_result = self._layers_permissions_list(opt, dry_run, &mut err); + }, + ("process", Some(opt)) => { + call_result = self._layers_process(opt, dry_run, &mut err); + }, + ("publish", Some(opt)) => { + call_result = self._layers_publish(opt, dry_run, &mut err); + }, + ("unpublish", Some(opt)) => { + call_result = self._layers_unpublish(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("layers".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("maps", Some(opt)) => { + match opt.subcommand() { + ("create", Some(opt)) => { + call_result = self._maps_create(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._maps_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._maps_get(opt, dry_run, &mut err); + }, + ("get-published", Some(opt)) => { + call_result = self._maps_get_published(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._maps_list(opt, dry_run, &mut err); + }, + ("list-published", Some(opt)) => { + call_result = self._maps_list_published(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._maps_patch(opt, dry_run, &mut err); + }, + ("permissions-batch-delete", Some(opt)) => { + call_result = self._maps_permissions_batch_delete(opt, dry_run, &mut err); + }, + ("permissions-batch-update", Some(opt)) => { + call_result = self._maps_permissions_batch_update(opt, dry_run, &mut err); + }, + ("permissions-list", Some(opt)) => { + call_result = self._maps_permissions_list(opt, dry_run, &mut err); + }, + ("publish", Some(opt)) => { + call_result = self._maps_publish(opt, dry_run, &mut err); + }, + ("unpublish", Some(opt)) => { + call_result = self._maps_unpublish(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("maps".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("projects", Some(opt)) => { + match opt.subcommand() { + ("icons-create", Some(opt)) => { + call_result = self._projects_icons_create(opt, dry_run, &mut err); + }, + ("icons-get", Some(opt)) => { + call_result = self._projects_icons_get(opt, dry_run, &mut err); + }, + ("icons-list", Some(opt)) => { + call_result = self._projects_icons_list(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._projects_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("projects".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("raster-collections", Some(opt)) => { + match opt.subcommand() { + ("cancel-processing", Some(opt)) => { + call_result = self._raster_collections_cancel_processing(opt, dry_run, &mut err); + }, + ("create", Some(opt)) => { + call_result = self._raster_collections_create(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._raster_collections_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._raster_collections_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._raster_collections_list(opt, dry_run, &mut err); + }, + ("parents-list", Some(opt)) => { + call_result = self._raster_collections_parents_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._raster_collections_patch(opt, dry_run, &mut err); + }, + ("permissions-batch-delete", Some(opt)) => { + call_result = self._raster_collections_permissions_batch_delete(opt, dry_run, &mut err); + }, + ("permissions-batch-update", Some(opt)) => { + call_result = self._raster_collections_permissions_batch_update(opt, dry_run, &mut err); + }, + ("permissions-list", Some(opt)) => { + call_result = self._raster_collections_permissions_list(opt, dry_run, &mut err); + }, + ("process", Some(opt)) => { + call_result = self._raster_collections_process(opt, dry_run, &mut err); + }, + ("rasters-batch-delete", Some(opt)) => { + call_result = self._raster_collections_rasters_batch_delete(opt, dry_run, &mut err); + }, + ("rasters-batch-insert", Some(opt)) => { + call_result = self._raster_collections_rasters_batch_insert(opt, dry_run, &mut err); + }, + ("rasters-list", Some(opt)) => { + call_result = self._raster_collections_rasters_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("raster-collections".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("rasters", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._rasters_delete(opt, dry_run, &mut err); + }, + ("files-insert", Some(opt)) => { + call_result = self._rasters_files_insert(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._rasters_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._rasters_list(opt, dry_run, &mut err); + }, + ("parents-list", Some(opt)) => { + call_result = self._rasters_parents_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._rasters_patch(opt, dry_run, &mut err); + }, + ("permissions-batch-delete", Some(opt)) => { + call_result = self._rasters_permissions_batch_delete(opt, dry_run, &mut err); + }, + ("permissions-batch-update", Some(opt)) => { + call_result = self._rasters_permissions_batch_update(opt, dry_run, &mut err); + }, + ("permissions-list", Some(opt)) => { + call_result = self._rasters_permissions_list(opt, dry_run, &mut err); + }, + ("process", Some(opt)) => { + call_result = self._rasters_process(opt, dry_run, &mut err); + }, + ("upload", Some(opt)) => { + call_result = self._rasters_upload(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("rasters".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("tables", Some(opt)) => { + match opt.subcommand() { + ("create", Some(opt)) => { + call_result = self._tables_create(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._tables_delete(opt, dry_run, &mut err); + }, + ("features-batch-delete", Some(opt)) => { + call_result = self._tables_features_batch_delete(opt, dry_run, &mut err); + }, + ("features-batch-insert", Some(opt)) => { + call_result = self._tables_features_batch_insert(opt, dry_run, &mut err); + }, + ("features-batch-patch", Some(opt)) => { + call_result = self._tables_features_batch_patch(opt, dry_run, &mut err); + }, + ("features-get", Some(opt)) => { + call_result = self._tables_features_get(opt, dry_run, &mut err); + }, + ("features-list", Some(opt)) => { + call_result = self._tables_features_list(opt, dry_run, &mut err); + }, + ("files-insert", Some(opt)) => { + call_result = self._tables_files_insert(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._tables_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._tables_list(opt, dry_run, &mut err); + }, + ("parents-list", Some(opt)) => { + call_result = self._tables_parents_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._tables_patch(opt, dry_run, &mut err); + }, + ("permissions-batch-delete", Some(opt)) => { + call_result = self._tables_permissions_batch_delete(opt, dry_run, &mut err); + }, + ("permissions-batch-update", Some(opt)) => { + call_result = self._tables_permissions_batch_update(opt, dry_run, &mut err); + }, + ("permissions-list", Some(opt)) => { + call_result = self._tables_permissions_list(opt, dry_run, &mut err); + }, + ("process", Some(opt)) => { + call_result = self._tables_process(opt, dry_run, &mut err); + }, + ("upload", Some(opt)) => { + call_result = self._tables_upload(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("tables".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_layers { - if self.opt.cmd_cancel_processing { - call_result = self._layers_cancel_processing(dry_run, &mut err); - } else if self.opt.cmd_create { - call_result = self._layers_create(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._layers_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._layers_get(dry_run, &mut err); - } else if self.opt.cmd_get_published { - call_result = self._layers_get_published(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._layers_list(dry_run, &mut err); - } else if self.opt.cmd_list_published { - call_result = self._layers_list_published(dry_run, &mut err); - } else if self.opt.cmd_parents_list { - call_result = self._layers_parents_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._layers_patch(dry_run, &mut err); - } else if self.opt.cmd_permissions_batch_delete { - call_result = self._layers_permissions_batch_delete(dry_run, &mut err); - } else if self.opt.cmd_permissions_batch_update { - call_result = self._layers_permissions_batch_update(dry_run, &mut err); - } else if self.opt.cmd_permissions_list { - call_result = self._layers_permissions_list(dry_run, &mut err); - } else if self.opt.cmd_process { - call_result = self._layers_process(dry_run, &mut err); - } else if self.opt.cmd_publish { - call_result = self._layers_publish(dry_run, &mut err); - } else if self.opt.cmd_unpublish { - call_result = self._layers_unpublish(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_maps { - if self.opt.cmd_create { - call_result = self._maps_create(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._maps_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._maps_get(dry_run, &mut err); - } else if self.opt.cmd_get_published { - call_result = self._maps_get_published(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._maps_list(dry_run, &mut err); - } else if self.opt.cmd_list_published { - call_result = self._maps_list_published(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._maps_patch(dry_run, &mut err); - } else if self.opt.cmd_permissions_batch_delete { - call_result = self._maps_permissions_batch_delete(dry_run, &mut err); - } else if self.opt.cmd_permissions_batch_update { - call_result = self._maps_permissions_batch_update(dry_run, &mut err); - } else if self.opt.cmd_permissions_list { - call_result = self._maps_permissions_list(dry_run, &mut err); - } else if self.opt.cmd_publish { - call_result = self._maps_publish(dry_run, &mut err); - } else if self.opt.cmd_unpublish { - call_result = self._maps_unpublish(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_projects { - if self.opt.cmd_icons_create { - call_result = self._projects_icons_create(dry_run, &mut err); - } else if self.opt.cmd_icons_get { - call_result = self._projects_icons_get(dry_run, &mut err); - } else if self.opt.cmd_icons_list { - call_result = self._projects_icons_list(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._projects_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_raster_collections { - if self.opt.cmd_cancel_processing { - call_result = self._raster_collections_cancel_processing(dry_run, &mut err); - } else if self.opt.cmd_create { - call_result = self._raster_collections_create(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._raster_collections_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._raster_collections_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._raster_collections_list(dry_run, &mut err); - } else if self.opt.cmd_parents_list { - call_result = self._raster_collections_parents_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._raster_collections_patch(dry_run, &mut err); - } else if self.opt.cmd_permissions_batch_delete { - call_result = self._raster_collections_permissions_batch_delete(dry_run, &mut err); - } else if self.opt.cmd_permissions_batch_update { - call_result = self._raster_collections_permissions_batch_update(dry_run, &mut err); - } else if self.opt.cmd_permissions_list { - call_result = self._raster_collections_permissions_list(dry_run, &mut err); - } else if self.opt.cmd_process { - call_result = self._raster_collections_process(dry_run, &mut err); - } else if self.opt.cmd_rasters_batch_delete { - call_result = self._raster_collections_rasters_batch_delete(dry_run, &mut err); - } else if self.opt.cmd_rasters_batch_insert { - call_result = self._raster_collections_rasters_batch_insert(dry_run, &mut err); - } else if self.opt.cmd_rasters_list { - call_result = self._raster_collections_rasters_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_rasters { - if self.opt.cmd_delete { - call_result = self._rasters_delete(dry_run, &mut err); - } else if self.opt.cmd_files_insert { - call_result = self._rasters_files_insert(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._rasters_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._rasters_list(dry_run, &mut err); - } else if self.opt.cmd_parents_list { - call_result = self._rasters_parents_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._rasters_patch(dry_run, &mut err); - } else if self.opt.cmd_permissions_batch_delete { - call_result = self._rasters_permissions_batch_delete(dry_run, &mut err); - } else if self.opt.cmd_permissions_batch_update { - call_result = self._rasters_permissions_batch_update(dry_run, &mut err); - } else if self.opt.cmd_permissions_list { - call_result = self._rasters_permissions_list(dry_run, &mut err); - } else if self.opt.cmd_process { - call_result = self._rasters_process(dry_run, &mut err); - } else if self.opt.cmd_upload { - call_result = self._rasters_upload(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_tables { - if self.opt.cmd_create { - call_result = self._tables_create(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._tables_delete(dry_run, &mut err); - } else if self.opt.cmd_features_batch_delete { - call_result = self._tables_features_batch_delete(dry_run, &mut err); - } else if self.opt.cmd_features_batch_insert { - call_result = self._tables_features_batch_insert(dry_run, &mut err); - } else if self.opt.cmd_features_batch_patch { - call_result = self._tables_features_batch_patch(dry_run, &mut err); - } else if self.opt.cmd_features_get { - call_result = self._tables_features_get(dry_run, &mut err); - } else if self.opt.cmd_features_list { - call_result = self._tables_features_list(dry_run, &mut err); - } else if self.opt.cmd_files_insert { - call_result = self._tables_files_insert(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._tables_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._tables_list(dry_run, &mut err); - } else if self.opt.cmd_parents_list { - call_result = self._tables_parents_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._tables_patch(dry_run, &mut err); - } else if self.opt.cmd_permissions_batch_delete { - call_result = self._tables_permissions_batch_delete(dry_run, &mut err); - } else if self.opt.cmd_permissions_batch_update { - call_result = self._tables_permissions_batch_update(dry_run, &mut err); - } else if self.opt.cmd_permissions_list { - call_result = self._tables_permissions_list(dry_run, &mut err); - } else if self.opt.cmd_process { - call_result = self._tables_process(dry_run, &mut err); - } else if self.opt.cmd_upload { - call_result = self._tables_upload(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -5760,7 +6015,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -5773,7 +6028,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -5783,37 +6038,1919 @@ impl Engine { let engine = Engine { opt: opt, hub: api::MapsEngine::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let upload_value_names = ["mode", "file"]; + let arg_data = [ + ("assets", "methods: 'get', 'list', 'parents-list' and 'permissions-list'", vec![ + ("get", + Some(r##"Return metadata for a particular asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/assets_get", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Return all assets readable by the current user."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/assets_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("parents-list", + Some(r##"Return all parent ids of the specified asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/assets_parents-list", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset whose parents will be listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-list", + Some(r##"Return all of the permissions for the specified asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/assets_permissions-list", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset whose permissions will be listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("layers", "methods: 'cancel-processing', 'create', 'delete', 'get', 'get-published', 'list', 'list-published', 'parents-list', 'patch', 'permissions-batch-delete', 'permissions-batch-update', 'permissions-list', 'process', 'publish' and 'unpublish'", vec![ + ("cancel-processing", + Some(r##"Cancel processing on a layer asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_cancel-processing", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the layer."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("create", + Some(r##"Create a layer asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_create", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Delete a layer."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the layer. Only the layer creator or project owner are permitted to delete. If the layer is published, or included in a map, the request will fail. Unpublish the layer, and remove it from all maps prior to deleting."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Return metadata for a particular layer."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_get", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the layer."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-published", + Some(r##"Return the published metadata for a particular layer."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_get-published", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the layer."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Return all layers readable by the current user."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-published", + Some(r##"Return all published layers readable by the current user."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_list-published", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("parents-list", + Some(r##"Return all parent ids of the specified layer."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_parents-list", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the layer whose parents will be listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Mutate a layer asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_patch", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the layer."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("permissions-batch-delete", + Some(r##"Remove permission entries from an already existing asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_permissions-batch-delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset from which permissions will be removed."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-batch-update", + Some(r##"Add or update permission entries to an already existing asset. + + An asset can hold up to 20 different permission entries. Each batchInsert request is atomic."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_permissions-batch-update", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset to which permissions will be added."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-list", + Some(r##"Return all of the permissions for the specified asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_permissions-list", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset whose permissions will be listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("process", + Some(r##"Process a layer asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_process", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the layer."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("publish", + Some(r##"Publish a layer asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_publish", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the layer."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("unpublish", + Some(r##"Unpublish a layer asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/layers_unpublish", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the layer."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("maps", "methods: 'create', 'delete', 'get', 'get-published', 'list', 'list-published', 'patch', 'permissions-batch-delete', 'permissions-batch-update', 'permissions-list', 'publish' and 'unpublish'", vec![ + ("create", + Some(r##"Create a map asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/maps_create", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Delete a map."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/maps_delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the map. Only the map creator or project owner are permitted to delete. If the map is published the request will fail. Unpublish the map prior to deleting."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Return metadata for a particular map."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/maps_get", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the map."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-published", + Some(r##"Return the published metadata for a particular map."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/maps_get-published", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the map."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Return all maps readable by the current user."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/maps_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-published", + Some(r##"Return all published maps readable by the current user."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/maps_list-published", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Mutate a map asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/maps_patch", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the map."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("permissions-batch-delete", + Some(r##"Remove permission entries from an already existing asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/maps_permissions-batch-delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset from which permissions will be removed."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-batch-update", + Some(r##"Add or update permission entries to an already existing asset. + + An asset can hold up to 20 different permission entries. Each batchInsert request is atomic."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/maps_permissions-batch-update", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset to which permissions will be added."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-list", + Some(r##"Return all of the permissions for the specified asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/maps_permissions-list", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset whose permissions will be listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("publish", + Some(r##"Publish a map asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/maps_publish", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the map."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("unpublish", + Some(r##"Unpublish a map asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/maps_unpublish", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the map."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("projects", "methods: 'icons-create', 'icons-get', 'icons-list' and 'list'", vec![ + ("icons-create", + Some(r##"Create an icon."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/projects_icons-create", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"The ID of the project."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("icons-get", + Some(r##"Return an icon or its associated metadata"##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/projects_icons-get", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"The ID of the project."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the icon."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("icons-list", + Some(r##"Return all icons in the current project"##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/projects_icons-list", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"The ID of the project."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Return all projects readable by the current user."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/projects_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("raster-collections", "methods: 'cancel-processing', 'create', 'delete', 'get', 'list', 'parents-list', 'patch', 'permissions-batch-delete', 'permissions-batch-update', 'permissions-list', 'process', 'rasters-batch-delete', 'rasters-batch-insert' and 'rasters-list'", vec![ + ("cancel-processing", + Some(r##"Cancel processing on a raster collection asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/raster-collections_cancel-processing", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the raster collection."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("create", + Some(r##"Create a raster collection asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/raster-collections_create", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Delete a raster collection."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/raster-collections_delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the raster collection. Only the raster collection creator or project owner are permitted to delete. If the rastor collection is included in a layer, the request will fail. Remove the raster collection from all layers prior to deleting."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Return metadata for a particular raster collection."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/raster-collections_get", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the raster collection."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Return all raster collections readable by the current user."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/raster-collections_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("parents-list", + Some(r##"Return all parent ids of the specified raster collection."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/raster-collections_parents-list", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the raster collection whose parents will be listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Mutate a raster collection asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/raster-collections_patch", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the raster collection."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("permissions-batch-delete", + Some(r##"Remove permission entries from an already existing asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/raster-collections_permissions-batch-delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset from which permissions will be removed."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-batch-update", + Some(r##"Add or update permission entries to an already existing asset. + + An asset can hold up to 20 different permission entries. Each batchInsert request is atomic."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/raster-collections_permissions-batch-update", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset to which permissions will be added."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-list", + Some(r##"Return all of the permissions for the specified asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/raster-collections_permissions-list", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset whose permissions will be listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("process", + Some(r##"Process a raster collection asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/raster-collections_process", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the raster collection."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("rasters-batch-delete", + Some(r##"Remove rasters from an existing raster collection. + + Up to 50 rasters can be included in a single batchDelete request. Each batchDelete request is atomic."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/raster-collections_rasters-batch-delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the raster collection to which these rasters belong."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("rasters-batch-insert", + Some(r##"Add rasters to an existing raster collection. Rasters must be successfully processed in order to be added to a raster collection. + + Up to 50 rasters can be included in a single batchInsert request. Each batchInsert request is atomic."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/raster-collections_rasters-batch-insert", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the raster collection to which these rasters belong."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("rasters-list", + Some(r##"Return all rasters within a raster collection."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/raster-collections_rasters-list", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the raster collection to which these rasters belong."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("rasters", "methods: 'delete', 'files-insert', 'get', 'list', 'parents-list', 'patch', 'permissions-batch-delete', 'permissions-batch-update', 'permissions-list', 'process' and 'upload'", vec![ + ("delete", + Some(r##"Delete a raster."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/rasters_delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the raster. Only the raster creator or project owner are permitted to delete. If the raster is included in a layer or mosaic, the request will fail. Remove it from all parents prior to deleting."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("files-insert", + Some(r##"Upload a file to a raster asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/rasters_files-insert", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the raster asset."##), + Some(true), + Some(false)), + + (Some(r##"filename"##), + None, + Some(r##"The file name of this uploaded file."##), + Some(true), + Some(false)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Return metadata for a single raster."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/rasters_get", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the raster."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Return all rasters readable by the current user."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/rasters_list", + vec![ + (Some(r##"project-id"##), + None, + Some(r##"The ID of a Maps Engine project, used to filter the response. To list all available projects with their IDs, send a Projects: list request. You can also find your project ID as the value of the DashboardPlace:cid URL parameter when signed in to mapsengine.google.com."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("parents-list", + Some(r##"Return all parent ids of the specified rasters."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/rasters_parents-list", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the rasters whose parents will be listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Mutate a raster asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/rasters_patch", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the raster."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("permissions-batch-delete", + Some(r##"Remove permission entries from an already existing asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/rasters_permissions-batch-delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset from which permissions will be removed."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-batch-update", + Some(r##"Add or update permission entries to an already existing asset. + + An asset can hold up to 20 different permission entries. Each batchInsert request is atomic."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/rasters_permissions-batch-update", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset to which permissions will be added."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-list", + Some(r##"Return all of the permissions for the specified asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/rasters_permissions-list", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset whose permissions will be listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("process", + Some(r##"Process a raster asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/rasters_process", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the raster."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("upload", + Some(r##"Create a skeleton raster asset for upload."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/rasters_upload", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("tables", "methods: 'create', 'delete', 'features-batch-delete', 'features-batch-insert', 'features-batch-patch', 'features-get', 'features-list', 'files-insert', 'get', 'list', 'parents-list', 'patch', 'permissions-batch-delete', 'permissions-batch-update', 'permissions-list', 'process' and 'upload'", vec![ + ("create", + Some(r##"Create a table asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_create", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Delete a table."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the table. Only the table creator or project owner are permitted to delete. If the table is included in a layer, the request will fail. Remove it from all layers prior to deleting."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("features-batch-delete", + Some(r##"Delete all features matching the given IDs."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_features-batch-delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the table that contains the features to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("features-batch-insert", + Some(r##"Append features to an existing table. + + A single batchInsert request can create: + + - Up to 50 features. + - A combined total of 10 000 vertices. + Feature limits are documented in the Supported data formats and limits article of the Google Maps Engine help center. Note that free and paid accounts have different limits. + + For more information about inserting features, read Creating features in the Google Maps Engine developer's guide."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_features-batch-insert", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the table to append the features to."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("features-batch-patch", + Some(r##"Update the supplied features. + + A single batchPatch request can update: + + - Up to 50 features. + - A combined total of 10 000 vertices. + Feature limits are documented in the Supported data formats and limits article of the Google Maps Engine help center. Note that free and paid accounts have different limits. + + Feature updates use HTTP PATCH semantics: + + - A supplied value replaces an existing value (if any) in that field. + - Omitted fields remain unchanged. + - Complex values in geometries and properties must be replaced as atomic units. For example, providing just the coordinates of a geometry is not allowed; the complete geometry, including type, must be supplied. + - Setting a property's value to null deletes that property. + For more information about updating features, read Updating features in the Google Maps Engine developer's guide."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_features-batch-patch", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the table containing the features to be patched."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("features-get", + Some(r##"Return a single feature, given its ID."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_features-get", + vec![ + (Some(r##"table-id"##), + None, + Some(r##"The ID of the table."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of the feature to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("features-list", + Some(r##"Return all features readable by the current user."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_features-list", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the table to which these features belong."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("files-insert", + Some(r##"Upload a file to a placeholder table asset. See Table Upload in the Developer's Guide for more information. + Supported file types are listed in the Supported data formats and limits article of the Google Maps Engine help center."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_files-insert", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the table asset."##), + Some(true), + Some(false)), + + (Some(r##"filename"##), + None, + Some(r##"The file name of this uploaded file."##), + Some(true), + Some(false)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Return metadata for a particular table, including the schema."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_get", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the table."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Return all tables readable by the current user."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("parents-list", + Some(r##"Return all parent ids of the specified table."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_parents-list", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the table whose parents will be listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Mutate a table asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_patch", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the table."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("permissions-batch-delete", + Some(r##"Remove permission entries from an already existing asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_permissions-batch-delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset from which permissions will be removed."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-batch-update", + Some(r##"Add or update permission entries to an already existing asset. + + An asset can hold up to 20 different permission entries. Each batchInsert request is atomic."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_permissions-batch-update", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset to which permissions will be added."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-list", + Some(r##"Return all of the permissions for the specified asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_permissions-list", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the asset whose permissions will be listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("process", + Some(r##"Process a table asset."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_process", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the table."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("upload", + Some(r##"Create a placeholder table asset to which table files can be uploaded. + Once the placeholder has been created, files are uploaded to the https://www.googleapis.com/upload/mapsengine/v1/tables/table_id/files endpoint. + See Table Upload in the Developer's Guide or Table.files: insert in the reference documentation for more information."##), + "Details at http://byron.github.io/google-apis-rs/google_mapsengine1_cli/tables_upload", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("mapsengine1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150414") + .about("The Google Maps Engine API allows developers to store and query geospatial vector and raster data.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_mapsengine1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + if arg_name_str == "mode" { + arg = arg.number_of_values(2); + arg = arg.value_names(&upload_value_names); + + scmd = scmd.arg(Arg::with_name("mime") + .short("m") + .requires("mode") + .required(false) + .help("The file's mime time, like 'application/octet-stream'") + .takes_value(true)); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/mapsengine1/Cargo.toml b/gen/mapsengine1/Cargo.toml index b6d8033a90..b5fc172377 100644 --- a/gen/mapsengine1/Cargo.toml +++ b/gen/mapsengine1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-mapsengine1" -version = "0.1.6+20150414" +version = "0.1.7+20150414" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with Maps Engine (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/mapsengine1" @@ -15,9 +15,10 @@ keywords = ["mapsengine", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/mapsengine1/README.md b/gen/mapsengine1/README.md index 2738129811..3de509e5ce 100644 --- a/gen/mapsengine1/README.md +++ b/gen/mapsengine1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-mapsengine1` library allows access to all features of the *Google Maps Engine* service. -This documentation was generated from *Maps Engine* crate version *0.1.6+20150414*, where *20150414* is the exact revision of the *mapsengine:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *Maps Engine* crate version *0.1.7+20150414*, where *20150414* is the exact revision of the *mapsengine:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *Maps Engine* *v1* API can be found at the [official documentation site](https://developers.google.com/maps-engine/). @@ -208,7 +208,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_mapsengine1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_mapsengine1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/mapsengine1/src/cmn.rs b/gen/mapsengine1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/mapsengine1/src/cmn.rs +++ b/gen/mapsengine1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/mapsengine1/src/lib.rs b/gen/mapsengine1/src/lib.rs index 9aa2863ad8..da9086b648 100644 --- a/gen/mapsengine1/src/lib.rs +++ b/gen/mapsengine1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *Maps Engine* crate version *0.1.6+20150414*, where *20150414* is the exact revision of the *mapsengine:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *Maps Engine* crate version *0.1.7+20150414*, where *20150414* is the exact revision of the *mapsengine:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *Maps Engine* *v1* API can be found at the //! [official documentation site](https://developers.google.com/maps-engine/). @@ -209,7 +209,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -218,7 +218,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -234,6 +233,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -367,7 +367,7 @@ impl<'a, C, A> MapsEngine<C, A> MapsEngine { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -394,7 +394,7 @@ impl<'a, C, A> MapsEngine<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -4196,7 +4196,7 @@ impl<'a, C, A> LayerUnpublishCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4218,7 +4218,7 @@ impl<'a, C, A> LayerUnpublishCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4440,7 +4440,7 @@ impl<'a, C, A> LayerPublishCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4462,7 +4462,7 @@ impl<'a, C, A> LayerPublishCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4675,7 +4675,7 @@ impl<'a, C, A> LayerListPublishedCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4697,7 +4697,7 @@ impl<'a, C, A> LayerListPublishedCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4878,6 +4878,7 @@ impl<'a, C, A> LayerCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Layer)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4911,11 +4912,20 @@ impl<'a, C, A> LayerCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4938,7 +4948,7 @@ impl<'a, C, A> LayerCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5164,7 +5174,7 @@ impl<'a, C, A> LayerGetPublishedCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5186,7 +5196,7 @@ impl<'a, C, A> LayerGetPublishedCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5402,7 +5412,7 @@ impl<'a, C, A> LayerDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5424,7 +5434,7 @@ impl<'a, C, A> LayerDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5636,7 +5646,7 @@ impl<'a, C, A> LayerGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5658,7 +5668,7 @@ impl<'a, C, A> LayerGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5834,6 +5844,7 @@ impl<'a, C, A> LayerPermissionBatchDeleteCall<'a, C, A> where C: BorrowMut<hyper /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PermissionsBatchDeleteResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5889,11 +5900,20 @@ impl<'a, C, A> LayerPermissionBatchDeleteCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5916,7 +5936,7 @@ impl<'a, C, A> LayerPermissionBatchDeleteCall<'a, C, A> where C: BorrowMut<hyper request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6099,6 +6119,7 @@ impl<'a, C, A> LayerPermissionBatchUpdateCall<'a, C, A> where C: BorrowMut<hyper /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PermissionsBatchUpdateResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6154,11 +6175,20 @@ impl<'a, C, A> LayerPermissionBatchUpdateCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6181,7 +6211,7 @@ impl<'a, C, A> LayerPermissionBatchUpdateCall<'a, C, A> where C: BorrowMut<hyper request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6449,7 +6479,7 @@ impl<'a, C, A> LayerListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6471,7 +6501,7 @@ impl<'a, C, A> LayerListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6778,7 +6808,7 @@ impl<'a, C, A> LayerParentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6800,7 +6830,7 @@ impl<'a, C, A> LayerParentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7031,7 +7061,7 @@ impl<'a, C, A> LayerCancelProcessingCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7053,7 +7083,7 @@ impl<'a, C, A> LayerCancelProcessingCall<'a, C, A> where C: BorrowMut<hyper::Cli access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7222,6 +7252,7 @@ impl<'a, C, A> LayerPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7276,11 +7307,20 @@ impl<'a, C, A> LayerPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7303,7 +7343,7 @@ impl<'a, C, A> LayerPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7522,7 +7562,7 @@ impl<'a, C, A> LayerPermissionListCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7544,7 +7584,7 @@ impl<'a, C, A> LayerPermissionListCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7761,7 +7801,7 @@ impl<'a, C, A> LayerProcesCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7783,7 +7823,7 @@ impl<'a, C, A> LayerProcesCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7954,6 +7994,7 @@ impl<'a, C, A> RasterPermissionBatchUpdateCall<'a, C, A> where C: BorrowMut<hype /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PermissionsBatchUpdateResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8009,11 +8050,20 @@ impl<'a, C, A> RasterPermissionBatchUpdateCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8036,7 +8086,7 @@ impl<'a, C, A> RasterPermissionBatchUpdateCall<'a, C, A> where C: BorrowMut<hype request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8217,6 +8267,7 @@ impl<'a, C, A> RasterPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8271,11 +8322,20 @@ impl<'a, C, A> RasterPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8298,7 +8358,7 @@ impl<'a, C, A> RasterPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8517,7 +8577,7 @@ impl<'a, C, A> RasterPermissionListCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8539,7 +8599,7 @@ impl<'a, C, A> RasterPermissionListCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8755,7 +8815,7 @@ impl<'a, C, A> RasterDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8777,7 +8837,7 @@ impl<'a, C, A> RasterDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8936,6 +8996,7 @@ impl<'a, C, A> RasterPermissionBatchDeleteCall<'a, C, A> where C: BorrowMut<hype /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PermissionsBatchDeleteResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8991,11 +9052,20 @@ impl<'a, C, A> RasterPermissionBatchDeleteCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9018,7 +9088,7 @@ impl<'a, C, A> RasterPermissionBatchDeleteCall<'a, C, A> where C: BorrowMut<hype request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9258,7 +9328,7 @@ impl<'a, C, A> RasterFileInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9296,7 +9366,7 @@ impl<'a, C, A> RasterFileInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, response } else { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); if protocol == "simple" { @@ -9354,7 +9424,7 @@ impl<'a, C, A> RasterFileInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -9382,6 +9452,7 @@ impl<'a, C, A> RasterFileInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -9598,7 +9669,7 @@ impl<'a, C, A> RasterProcesCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9620,7 +9691,7 @@ impl<'a, C, A> RasterProcesCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9837,7 +9908,7 @@ impl<'a, C, A> RasterGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9859,7 +9930,7 @@ impl<'a, C, A> RasterGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10112,7 +10183,7 @@ impl<'a, C, A> RasterListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10134,7 +10205,7 @@ impl<'a, C, A> RasterListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10385,6 +10456,7 @@ impl<'a, C, A> RasterUploadCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Raster)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10415,11 +10487,20 @@ impl<'a, C, A> RasterUploadCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10442,7 +10523,7 @@ impl<'a, C, A> RasterUploadCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -10671,7 +10752,7 @@ impl<'a, C, A> RasterParentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10693,7 +10774,7 @@ impl<'a, C, A> RasterParentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10924,7 +11005,7 @@ impl<'a, C, A> AssetPermissionListCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10946,7 +11027,7 @@ impl<'a, C, A> AssetPermissionListCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11202,7 +11283,7 @@ impl<'a, C, A> AssetListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11224,7 +11305,7 @@ impl<'a, C, A> AssetListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11522,7 +11603,7 @@ impl<'a, C, A> AssetGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11544,7 +11625,7 @@ impl<'a, C, A> AssetGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11771,7 +11852,7 @@ impl<'a, C, A> AssetParentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11793,7 +11874,7 @@ impl<'a, C, A> AssetParentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12023,7 +12104,7 @@ impl<'a, C, A> TableDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12045,7 +12126,7 @@ impl<'a, C, A> TableDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12264,7 +12345,7 @@ impl<'a, C, A> TableFileInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12302,7 +12383,7 @@ impl<'a, C, A> TableFileInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, response } else { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); if protocol == "simple" { @@ -12360,7 +12441,7 @@ impl<'a, C, A> TableFileInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -12388,6 +12469,7 @@ impl<'a, C, A> TableFileInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -12564,6 +12646,7 @@ impl<'a, C, A> TableFeatureBatchInsertCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12618,11 +12701,20 @@ impl<'a, C, A> TableFeatureBatchInsertCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12645,7 +12737,7 @@ impl<'a, C, A> TableFeatureBatchInsertCall<'a, C, A> where C: BorrowMut<hyper::C request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -12903,7 +12995,7 @@ impl<'a, C, A> TableListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12925,7 +13017,7 @@ impl<'a, C, A> TableListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -13227,7 +13319,7 @@ impl<'a, C, A> TableGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13249,7 +13341,7 @@ impl<'a, C, A> TableGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -13424,6 +13516,7 @@ impl<'a, C, A> TableFeatureBatchDeleteCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13478,11 +13571,20 @@ impl<'a, C, A> TableFeatureBatchDeleteCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13505,7 +13607,7 @@ impl<'a, C, A> TableFeatureBatchDeleteCall<'a, C, A> where C: BorrowMut<hyper::C request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -13769,7 +13871,7 @@ impl<'a, C, A> TableFeatureListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13791,7 +13893,7 @@ impl<'a, C, A> TableFeatureListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -14071,7 +14173,7 @@ impl<'a, C, A> TableProcesCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14093,7 +14195,7 @@ impl<'a, C, A> TableProcesCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -14320,7 +14422,7 @@ impl<'a, C, A> TableParentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14342,7 +14444,7 @@ impl<'a, C, A> TableParentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -14527,6 +14629,7 @@ impl<'a, C, A> TablePermissionBatchUpdateCall<'a, C, A> where C: BorrowMut<hyper /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PermissionsBatchUpdateResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14582,11 +14685,20 @@ impl<'a, C, A> TablePermissionBatchUpdateCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14609,7 +14721,7 @@ impl<'a, C, A> TablePermissionBatchUpdateCall<'a, C, A> where C: BorrowMut<hyper request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -14791,6 +14903,7 @@ impl<'a, C, A> TableUploadCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Table)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14821,11 +14934,20 @@ impl<'a, C, A> TableUploadCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -14848,7 +14970,7 @@ impl<'a, C, A> TableUploadCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -15033,6 +15155,7 @@ impl<'a, C, A> TableFeatureBatchPatchCall<'a, C, A> where C: BorrowMut<hyper::Cl /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15087,11 +15210,20 @@ impl<'a, C, A> TableFeatureBatchPatchCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15114,7 +15246,7 @@ impl<'a, C, A> TableFeatureBatchPatchCall<'a, C, A> where C: BorrowMut<hyper::Cl request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -15285,6 +15417,7 @@ impl<'a, C, A> TablePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15339,11 +15472,20 @@ impl<'a, C, A> TablePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15366,7 +15508,7 @@ impl<'a, C, A> TablePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -15537,6 +15679,7 @@ impl<'a, C, A> TablePermissionBatchDeleteCall<'a, C, A> where C: BorrowMut<hyper /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PermissionsBatchDeleteResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15592,11 +15735,20 @@ impl<'a, C, A> TablePermissionBatchDeleteCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15619,7 +15771,7 @@ impl<'a, C, A> TablePermissionBatchDeleteCall<'a, C, A> where C: BorrowMut<hyper request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -15799,6 +15951,7 @@ impl<'a, C, A> TableCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Table)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15829,11 +15982,20 @@ impl<'a, C, A> TableCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15856,7 +16018,7 @@ impl<'a, C, A> TableCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -16075,7 +16237,7 @@ impl<'a, C, A> TablePermissionListCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16097,7 +16259,7 @@ impl<'a, C, A> TablePermissionListCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -16326,7 +16488,7 @@ impl<'a, C, A> TableFeatureGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16348,7 +16510,7 @@ impl<'a, C, A> TableFeatureGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -16628,7 +16790,7 @@ impl<'a, C, A> MapListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16650,7 +16812,7 @@ impl<'a, C, A> MapListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -16936,7 +17098,7 @@ impl<'a, C, A> MapListPublishedCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16958,7 +17120,7 @@ impl<'a, C, A> MapListPublishedCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -17138,6 +17300,7 @@ impl<'a, C, A> MapPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17192,11 +17355,20 @@ impl<'a, C, A> MapPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17219,7 +17391,7 @@ impl<'a, C, A> MapPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -17392,6 +17564,7 @@ impl<'a, C, A> MapPermissionBatchUpdateCall<'a, C, A> where C: BorrowMut<hyper:: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PermissionsBatchUpdateResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17447,11 +17620,20 @@ impl<'a, C, A> MapPermissionBatchUpdateCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17474,7 +17656,7 @@ impl<'a, C, A> MapPermissionBatchUpdateCall<'a, C, A> where C: BorrowMut<hyper:: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -17702,7 +17884,7 @@ impl<'a, C, A> MapDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17724,7 +17906,7 @@ impl<'a, C, A> MapDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -17931,7 +18113,7 @@ impl<'a, C, A> MapUnpublishCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17953,7 +18135,7 @@ impl<'a, C, A> MapUnpublishCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -18175,7 +18357,7 @@ impl<'a, C, A> MapPublishCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18197,7 +18379,7 @@ impl<'a, C, A> MapPublishCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -18421,7 +18603,7 @@ impl<'a, C, A> MapPermissionListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18443,7 +18625,7 @@ impl<'a, C, A> MapPermissionListCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -18611,6 +18793,7 @@ impl<'a, C, A> MapCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Map)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -18641,11 +18824,20 @@ impl<'a, C, A> MapCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -18668,7 +18860,7 @@ impl<'a, C, A> MapCreateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -18887,7 +19079,7 @@ impl<'a, C, A> MapGetPublishedCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18909,7 +19101,7 @@ impl<'a, C, A> MapGetPublishedCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -19131,7 +19323,7 @@ impl<'a, C, A> MapGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth2 if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19153,7 +19345,7 @@ impl<'a, C, A> MapGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth2 access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -19329,6 +19521,7 @@ impl<'a, C, A> MapPermissionBatchDeleteCall<'a, C, A> where C: BorrowMut<hyper:: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PermissionsBatchDeleteResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -19384,11 +19577,20 @@ impl<'a, C, A> MapPermissionBatchDeleteCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -19411,7 +19613,7 @@ impl<'a, C, A> MapPermissionBatchDeleteCall<'a, C, A> where C: BorrowMut<hyper:: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -19591,6 +19793,7 @@ impl<'a, C, A> RasterCollectionCreateCall<'a, C, A> where C: BorrowMut<hyper::Cl /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, RasterCollection)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -19621,11 +19824,20 @@ impl<'a, C, A> RasterCollectionCreateCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -19648,7 +19860,7 @@ impl<'a, C, A> RasterCollectionCreateCall<'a, C, A> where C: BorrowMut<hyper::Cl request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -19819,6 +20031,7 @@ impl<'a, C, A> RasterCollectionPermissionBatchDeleteCall<'a, C, A> where C: Borr /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PermissionsBatchDeleteResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -19874,11 +20087,20 @@ impl<'a, C, A> RasterCollectionPermissionBatchDeleteCall<'a, C, A> where C: Borr if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -19901,7 +20123,7 @@ impl<'a, C, A> RasterCollectionPermissionBatchDeleteCall<'a, C, A> where C: Borr request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -20082,6 +20304,7 @@ impl<'a, C, A> RasterCollectionPatchCall<'a, C, A> where C: BorrowMut<hyper::Cli /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -20136,11 +20359,20 @@ impl<'a, C, A> RasterCollectionPatchCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -20163,7 +20395,7 @@ impl<'a, C, A> RasterCollectionPatchCall<'a, C, A> where C: BorrowMut<hyper::Cli request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -20382,7 +20614,7 @@ impl<'a, C, A> RasterCollectionCancelProcessingCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -20404,7 +20636,7 @@ impl<'a, C, A> RasterCollectionCancelProcessingCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -20621,7 +20853,7 @@ impl<'a, C, A> RasterCollectionProcesCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -20643,7 +20875,7 @@ impl<'a, C, A> RasterCollectionProcesCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -20814,6 +21046,7 @@ impl<'a, C, A> RasterCollectionPermissionBatchUpdateCall<'a, C, A> where C: Borr /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PermissionsBatchUpdateResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -20869,11 +21102,20 @@ impl<'a, C, A> RasterCollectionPermissionBatchUpdateCall<'a, C, A> where C: Borr if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -20896,7 +21138,7 @@ impl<'a, C, A> RasterCollectionPermissionBatchUpdateCall<'a, C, A> where C: Borr request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -21124,7 +21366,7 @@ impl<'a, C, A> RasterCollectionDeleteCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -21146,7 +21388,7 @@ impl<'a, C, A> RasterCollectionDeleteCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -21363,7 +21605,7 @@ impl<'a, C, A> RasterCollectionParentListCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -21385,7 +21627,7 @@ impl<'a, C, A> RasterCollectionParentListCall<'a, C, A> where C: BorrowMut<hyper access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -21655,7 +21897,7 @@ impl<'a, C, A> RasterCollectionListCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -21677,7 +21919,7 @@ impl<'a, C, A> RasterCollectionListCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -21928,6 +22170,7 @@ impl<'a, C, A> RasterCollectionRasterBatchInsertCall<'a, C, A> where C: BorrowMu /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, RasterCollectionsRastersBatchInsertResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -21983,11 +22226,20 @@ impl<'a, C, A> RasterCollectionRasterBatchInsertCall<'a, C, A> where C: BorrowMu if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -22010,7 +22262,7 @@ impl<'a, C, A> RasterCollectionRasterBatchInsertCall<'a, C, A> where C: BorrowMu request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -22193,6 +22445,7 @@ impl<'a, C, A> RasterCollectionRasterBatchDeleteCall<'a, C, A> where C: BorrowMu /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, RasterCollectionsRastersBatchDeleteResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -22248,11 +22501,20 @@ impl<'a, C, A> RasterCollectionRasterBatchDeleteCall<'a, C, A> where C: BorrowMu if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -22275,7 +22537,7 @@ impl<'a, C, A> RasterCollectionRasterBatchDeleteCall<'a, C, A> where C: BorrowMu request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -22504,7 +22766,7 @@ impl<'a, C, A> RasterCollectionPermissionListCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -22526,7 +22788,7 @@ impl<'a, C, A> RasterCollectionPermissionListCall<'a, C, A> where C: BorrowMut<h access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -22743,7 +23005,7 @@ impl<'a, C, A> RasterCollectionGetCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -22765,7 +23027,7 @@ impl<'a, C, A> RasterCollectionGetCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -23037,7 +23299,7 @@ impl<'a, C, A> RasterCollectionRasterListCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -23059,7 +23321,7 @@ impl<'a, C, A> RasterCollectionRasterListCall<'a, C, A> where C: BorrowMut<hyper access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -23376,7 +23638,7 @@ impl<'a, C, A> ProjectIconGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -23398,7 +23660,7 @@ impl<'a, C, A> ProjectIconGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -23579,6 +23841,7 @@ impl<'a, C, A> ProjectIconCreateCall<'a, C, A> where C: BorrowMut<hyper::Client> /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, Icon)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -23642,11 +23905,20 @@ impl<'a, C, A> ProjectIconCreateCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -23701,7 +23973,7 @@ impl<'a, C, A> ProjectIconCreateCall<'a, C, A> where C: BorrowMut<hyper::Client> _ => (&mut request_value_reader as &mut io::Read, ContentType(json_mime_type.clone())), }; let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(content_type) @@ -23751,7 +24023,7 @@ impl<'a, C, A> ProjectIconCreateCall<'a, C, A> where C: BorrowMut<hyper::Client> let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -23779,6 +24051,7 @@ impl<'a, C, A> ProjectIconCreateCall<'a, C, A> where C: BorrowMut<hyper::Client> Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -23978,7 +24251,7 @@ impl<'a, C, A> ProjectListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -24000,7 +24273,7 @@ impl<'a, C, A> ProjectListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -24217,7 +24490,7 @@ impl<'a, C, A> ProjectIconListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -24239,7 +24512,7 @@ impl<'a, C, A> ProjectIconListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/mirror1-cli/Cargo.toml b/gen/mirror1-cli/Cargo.toml index 74f034b3ec..8503a0a0ab 100644 --- a/gen/mirror1-cli/Cargo.toml +++ b/gen/mirror1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-mirror1-cli" -version = "0.1.0+20150220" +version = "0.2.0+20150220" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with mirror (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/mirror1-cli" @@ -17,15 +17,14 @@ keywords = ["mirror", "google", "cli"] name = "mirror1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-mirror1] path = "../mirror1" diff --git a/gen/mirror1-cli/README.md b/gen/mirror1-cli/README.md index 4b834a2fcf..306271943a 100644 --- a/gen/mirror1-cli/README.md +++ b/gen/mirror1-cli/README.md @@ -10,44 +10,51 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *mirror* API can be found at the +[official documentation site](https://developers.google.com/glass). + # Usage -This documentation was generated from the *mirror* API at revision *20150220*. The CLI is at version *0.1.0*. +This documentation was generated from the *mirror* API at revision *20150220*. The CLI is at version *0.2.0*. ```bash - mirror1 [options] accounts insert <user-token> <account-type> <account-name> -r <kv>... [-p <v>...] [-o <out>] - mirror1 [options] contacts delete <id> [-p <v>...] - mirror1 [options] contacts get <id> [-p <v>...] [-o <out>] - mirror1 [options] contacts insert -r <kv>... [-p <v>...] [-o <out>] - mirror1 [options] contacts list [-p <v>...] [-o <out>] - mirror1 [options] contacts patch <id> -r <kv>... [-p <v>...] [-o <out>] - mirror1 [options] contacts update <id> -r <kv>... [-p <v>...] [-o <out>] - mirror1 [options] locations get <id> [-p <v>...] [-o <out>] - mirror1 [options] locations list [-p <v>...] [-o <out>] - mirror1 [options] settings get <id> [-p <v>...] [-o <out>] - mirror1 [options] subscriptions delete <id> [-p <v>...] - mirror1 [options] subscriptions insert -r <kv>... [-p <v>...] [-o <out>] - mirror1 [options] subscriptions list [-p <v>...] [-o <out>] - mirror1 [options] subscriptions update <id> -r <kv>... [-p <v>...] [-o <out>] - mirror1 [options] timeline attachments-delete <item-id> <attachment-id> [-p <v>...] - mirror1 [options] timeline attachments-get <item-id> <attachment-id> [-p <v>...] [-o <out>] - mirror1 [options] timeline attachments-insert <item-id> -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - mirror1 [options] timeline attachments-list <item-id> [-p <v>...] [-o <out>] - mirror1 [options] timeline delete <id> [-p <v>...] - mirror1 [options] timeline get <id> [-p <v>...] [-o <out>] - mirror1 [options] timeline insert -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - mirror1 [options] timeline list [-p <v>...] [-o <out>] - mirror1 [options] timeline patch <id> -r <kv>... [-p <v>...] [-o <out>] - mirror1 [options] timeline update <id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] +mirror1 [options] + accounts + insert <user-token> <account-type> <account-name> (-r <kv>)... [-p <v>]... [-o <out>] + contacts + delete <id> [-p <v>]... + get <id> [-p <v>]... [-o <out>] + insert (-r <kv>)... [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + patch <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <id> (-r <kv>)... [-p <v>]... [-o <out>] + locations + get <id> [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + settings + get <id> [-p <v>]... [-o <out>] + subscriptions + delete <id> [-p <v>]... + insert (-r <kv>)... [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + update <id> (-r <kv>)... [-p <v>]... [-o <out>] + timeline + attachments-delete <item-id> <attachment-id> [-p <v>]... + attachments-get <item-id> <attachment-id> [-p <v>]... [-o <out>] + attachments-insert <item-id> (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + attachments-list <item-id> [-p <v>]... [-o <out>] + delete <id> [-p <v>]... + get <id> [-p <v>]... [-o <out>] + insert (-r <kv>)... (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + patch <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <id> (-r <kv>)... (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] mirror1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_mirror1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/mirror1-cli/mkdocs.yml b/gen/mirror1-cli/mkdocs.yml index 67795a8215..dcb339ff96 100644 --- a/gen/mirror1-cli/mkdocs.yml +++ b/gen/mirror1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: mirror v0.1.0+20150220 +site_name: mirror v0.2.0+20150220 site_url: http://byron.github.io/google-apis-rs/google-mirror1-cli site_description: Write integrating applications with bcore diff --git a/gen/mirror1-cli/src/cmn.rs b/gen/mirror1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/mirror1-cli/src/cmn.rs +++ b/gen/mirror1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/mirror1-cli/src/main.rs b/gen/mirror1-cli/src/main.rs index 3157409e1f..9de43bae26 100644 --- a/gen/mirror1-cli/src/main.rs +++ b/gen/mirror1-cli/src/main.rs @@ -2,92 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_mirror1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - mirror1 [options] accounts insert <user-token> <account-type> <account-name> -r <kv>... [-p <v>...] [-o <out>] - mirror1 [options] contacts delete <id> [-p <v>...] - mirror1 [options] contacts get <id> [-p <v>...] [-o <out>] - mirror1 [options] contacts insert -r <kv>... [-p <v>...] [-o <out>] - mirror1 [options] contacts list [-p <v>...] [-o <out>] - mirror1 [options] contacts patch <id> -r <kv>... [-p <v>...] [-o <out>] - mirror1 [options] contacts update <id> -r <kv>... [-p <v>...] [-o <out>] - mirror1 [options] locations get <id> [-p <v>...] [-o <out>] - mirror1 [options] locations list [-p <v>...] [-o <out>] - mirror1 [options] settings get <id> [-p <v>...] [-o <out>] - mirror1 [options] subscriptions delete <id> [-p <v>...] - mirror1 [options] subscriptions insert -r <kv>... [-p <v>...] [-o <out>] - mirror1 [options] subscriptions list [-p <v>...] [-o <out>] - mirror1 [options] subscriptions update <id> -r <kv>... [-p <v>...] [-o <out>] - mirror1 [options] timeline attachments-delete <item-id> <attachment-id> [-p <v>...] - mirror1 [options] timeline attachments-get <item-id> <attachment-id> [-p <v>...] [-o <out>] - mirror1 [options] timeline attachments-insert <item-id> -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - mirror1 [options] timeline attachments-list <item-id> [-p <v>...] [-o <out>] - mirror1 [options] timeline delete <id> [-p <v>...] - mirror1 [options] timeline get <id> [-p <v>...] [-o <out>] - mirror1 [options] timeline insert -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - mirror1 [options] timeline list [-p <v>...] [-o <out>] - mirror1 [options] timeline patch <id> -r <kv>... [-p <v>...] [-o <out>] - mirror1 [options] timeline update <id> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - mirror1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_mirror1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Mirror<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _accounts_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _accounts_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Account::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -112,147 +75,155 @@ impl Engine { request.features.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["features", "password"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().insert(request, &self.opt.arg_user_token, &self.opt.arg_account_type, &self.opt.arg_account_name); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().insert(request, opt.value_of("user-token").unwrap_or(""), opt.value_of("account-type").unwrap_or(""), opt.value_of("account-name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _contacts_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.contacts().delete(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _contacts_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.contacts().delete(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _contacts_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.contacts().get(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _contacts_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.contacts().get(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _contacts_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _contacts_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Contact::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -310,106 +281,115 @@ impl Engine { request.speakable_name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["accept-types", "display-name", "id", "image-urls", "kind", "phone-number", "priority", "sharing-features", "source", "speakable-name", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.contacts().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _contacts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _contacts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.contacts().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _contacts_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _contacts_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Contact::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -467,60 +447,65 @@ impl Engine { request.speakable_name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["accept-types", "display-name", "id", "image-urls", "kind", "phone-number", "priority", "sharing-features", "source", "speakable-name", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.contacts().patch(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.contacts().patch(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _contacts_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _contacts_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Contact::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -578,242 +563,258 @@ impl Engine { request.speakable_name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["accept-types", "display-name", "id", "image-urls", "kind", "phone-number", "priority", "sharing-features", "source", "speakable-name", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.contacts().update(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.contacts().update(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _locations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.locations().get(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _locations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.locations().get(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _locations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _locations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.locations().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _settings_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.settings().get(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _settings_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.settings().get(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _subscriptions_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.subscriptions().delete(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _subscriptions_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.subscriptions().delete(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _subscriptions_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _subscriptions_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Subscription::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -889,106 +890,115 @@ impl Engine { request.callback_url = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["callback-url", "collection", "id", "item-id", "kind", "notification", "operation", "updated", "user-token", "verify-token"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.subscriptions().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _subscriptions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _subscriptions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.subscriptions().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _subscriptions_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _subscriptions_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Subscription::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1064,350 +1074,363 @@ impl Engine { request.callback_url = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["callback-url", "collection", "id", "item-id", "kind", "notification", "operation", "updated", "user-token", "verify-token"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.subscriptions().update(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.subscriptions().update(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _timeline_attachments_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.timeline().attachments_delete(&self.opt.arg_item_id, &self.opt.arg_attachment_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok(mut response) => { - None - } - } - } - } - - fn _timeline_attachments_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut download_mode = false; - let mut call = self.hub.timeline().attachments_get(&self.opt.arg_item_id, &self.opt.arg_attachment_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _timeline_attachments_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.timeline().attachments_delete(opt.value_of("item-id").unwrap_or(""), opt.value_of("attachment-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok(mut response) => { + Ok(()) + } + } + } + } + + fn _timeline_attachments_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut download_mode = false; + let mut call = self.hub.timeline().attachments_get(opt.value_of("item-id").unwrap_or(""), opt.value_of("attachment-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let protocol = CallType::Standard; + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { if !download_mode { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); } else { io::copy(&mut response, &mut ostream).unwrap(); } - None + Ok(()) } } } } - fn _timeline_attachments_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.timeline().attachments_insert(&self.opt.arg_item_id); - for parg in self.opt.arg_v.iter() { + fn _timeline_attachments_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.timeline().attachments_insert(opt.value_of("item-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _timeline_attachments_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.timeline().attachments_list(&self.opt.arg_item_id); - for parg in self.opt.arg_v.iter() { + fn _timeline_attachments_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.timeline().attachments_list(opt.value_of("item-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _timeline_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.timeline().delete(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _timeline_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.timeline().delete(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _timeline_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.timeline().get(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _timeline_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.timeline().get(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _timeline_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _timeline_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TimelineItem::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1613,68 +1636,67 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["accept-types", "accuracy", "address", "bundle-id", "canonical-url", "created", "creator", "delivery-time", "display-name", "display-time", "etag", "html", "id", "image-urls", "in-reply-to", "is-bundle-cover", "is-deleted", "is-pinned", "kind", "latitude", "level", "location", "longitude", "notification", "phone-number", "pin-score", "priority", "self-link", "sharing-features", "source", "source-item-id", "speakable-name", "speakable-text", "speakable-type", "text", "timestamp", "title", "type", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.timeline().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() - }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _timeline_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _timeline_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.timeline().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source-item-id" => { @@ -1698,672 +1720,727 @@ impl Engine { "bundle-id" => { call = call.bundle_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["order-by", "include-deleted", "max-results", "page-token", "source-item-id", "pinned-only", "bundle-id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _timeline_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - - let mut request = api::TimelineItem::default(); - let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { - let last_errc = err.issues.len(); - let (key, value) = parse_kv_arg(&*kvarg, err, false); - let mut temp_cursor = field_cursor.clone(); - if let Err(field_err) = temp_cursor.set(&*key) { - err.issues.push(field_err); - } - if value.is_none() { - field_cursor = temp_cursor.clone(); - if err.issues.len() > last_errc { - err.issues.remove(last_errc); - } - continue; - } - fn request_creator_init(request: &mut api::TimelineItem) { - if request.creator.is_none() { - request.creator = Some(Default::default()); - } - } - - fn request_location_init(request: &mut api::TimelineItem) { - if request.location.is_none() { - request.location = Some(Default::default()); - } - } - - fn request_notification_init(request: &mut api::TimelineItem) { - if request.notification.is_none() { - request.notification = Some(Default::default()); - } - } - - match &temp_cursor.to_string()[..] { - "display-time" => { - request.display_time = Some(value.unwrap_or("").to_string()); - }, - "creator.kind" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "creator.display-name" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().display_name = Some(value.unwrap_or("").to_string()); - }, - "creator.accept-types" => { - request_creator_init(&mut request); - if request.creator.as_mut().unwrap().accept_types.is_none() { - request.creator.as_mut().unwrap().accept_types = Some(Default::default()); - } - request.creator.as_mut().unwrap().accept_types.as_mut().unwrap().push(value.unwrap_or("").to_string()); - }, - "creator.image-urls" => { - request_creator_init(&mut request); - if request.creator.as_mut().unwrap().image_urls.is_none() { - request.creator.as_mut().unwrap().image_urls = Some(Default::default()); - } - request.creator.as_mut().unwrap().image_urls.as_mut().unwrap().push(value.unwrap_or("").to_string()); - }, - "creator.priority" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().priority = Some(arg_from_str(value.unwrap_or("-0"), err, "creator.priority", "integer")); - }, - "creator.source" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().source = Some(value.unwrap_or("").to_string()); - }, - "creator.phone-number" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().phone_number = Some(value.unwrap_or("").to_string()); - }, - "creator.sharing-features" => { - request_creator_init(&mut request); - if request.creator.as_mut().unwrap().sharing_features.is_none() { - request.creator.as_mut().unwrap().sharing_features = Some(Default::default()); - } - request.creator.as_mut().unwrap().sharing_features.as_mut().unwrap().push(value.unwrap_or("").to_string()); - }, - "creator.type" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); - }, - "creator.id" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); - }, - "creator.speakable-name" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().speakable_name = Some(value.unwrap_or("").to_string()); - }, - "text" => { - request_creator_init(&mut request); - request.text = Some(value.unwrap_or("").to_string()); - }, - "is-bundle-cover" => { - request_creator_init(&mut request); - request.is_bundle_cover = Some(arg_from_str(value.unwrap_or("false"), err, "is-bundle-cover", "boolean")); - }, - "etag" => { - request_creator_init(&mut request); - request.etag = Some(value.unwrap_or("").to_string()); - }, - "id" => { - request_creator_init(&mut request); - request.id = Some(value.unwrap_or("").to_string()); - }, - "is-deleted" => { - request_creator_init(&mut request); - request.is_deleted = Some(arg_from_str(value.unwrap_or("false"), err, "is-deleted", "boolean")); - }, - "bundle-id" => { - request_creator_init(&mut request); - request.bundle_id = Some(value.unwrap_or("").to_string()); - }, - "is-pinned" => { - request_creator_init(&mut request); - request.is_pinned = Some(arg_from_str(value.unwrap_or("false"), err, "is-pinned", "boolean")); - }, - "title" => { - request_creator_init(&mut request); - request.title = Some(value.unwrap_or("").to_string()); - }, - "pin-score" => { - request_creator_init(&mut request); - request.pin_score = Some(arg_from_str(value.unwrap_or("-0"), err, "pin-score", "integer")); - }, - "speakable-text" => { - request_creator_init(&mut request); - request.speakable_text = Some(value.unwrap_or("").to_string()); - }, - "html" => { - request_creator_init(&mut request); - request.html = Some(value.unwrap_or("").to_string()); - }, - "location.kind" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "location.display-name" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().display_name = Some(value.unwrap_or("").to_string()); - }, - "location.timestamp" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().timestamp = Some(value.unwrap_or("").to_string()); - }, - "location.longitude" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().longitude = Some(arg_from_str(value.unwrap_or("0.0"), err, "location.longitude", "number")); - }, - "location.address" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().address = Some(value.unwrap_or("").to_string()); - }, - "location.latitude" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().latitude = Some(arg_from_str(value.unwrap_or("0.0"), err, "location.latitude", "number")); - }, - "location.id" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); - }, - "location.accuracy" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().accuracy = Some(arg_from_str(value.unwrap_or("0.0"), err, "location.accuracy", "number")); - }, - "source-item-id" => { - request_location_init(&mut request); - request.source_item_id = Some(value.unwrap_or("").to_string()); - }, - "in-reply-to" => { - request_location_init(&mut request); - request.in_reply_to = Some(value.unwrap_or("").to_string()); - }, - "updated" => { - request_location_init(&mut request); - request.updated = Some(value.unwrap_or("").to_string()); - }, - "canonical-url" => { - request_location_init(&mut request); - request.canonical_url = Some(value.unwrap_or("").to_string()); - }, - "kind" => { - request_location_init(&mut request); - request.kind = Some(value.unwrap_or("").to_string()); - }, - "created" => { - request_location_init(&mut request); - request.created = Some(value.unwrap_or("").to_string()); - }, - "notification.level" => { - request_notification_init(&mut request); - request.notification.as_mut().unwrap().level = Some(value.unwrap_or("").to_string()); - }, - "notification.delivery-time" => { - request_notification_init(&mut request); - request.notification.as_mut().unwrap().delivery_time = Some(value.unwrap_or("").to_string()); - }, - "speakable-type" => { - request_notification_init(&mut request); - request.speakable_type = Some(value.unwrap_or("").to_string()); - }, - "self-link" => { - request_notification_init(&mut request); - request.self_link = Some(value.unwrap_or("").to_string()); - }, - _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); - } - } - } - let mut call = self.hub.timeline().patch(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = "standard-request"; - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); - match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), - } { - Err(api_err) => Some(api_err), - Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None - } - } - } - } - - fn _timeline_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - - let mut request = api::TimelineItem::default(); - let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { - let last_errc = err.issues.len(); - let (key, value) = parse_kv_arg(&*kvarg, err, false); - let mut temp_cursor = field_cursor.clone(); - if let Err(field_err) = temp_cursor.set(&*key) { - err.issues.push(field_err); - } - if value.is_none() { - field_cursor = temp_cursor.clone(); - if err.issues.len() > last_errc { - err.issues.remove(last_errc); - } - continue; - } - fn request_creator_init(request: &mut api::TimelineItem) { - if request.creator.is_none() { - request.creator = Some(Default::default()); - } - } - - fn request_location_init(request: &mut api::TimelineItem) { - if request.location.is_none() { - request.location = Some(Default::default()); - } - } - - fn request_notification_init(request: &mut api::TimelineItem) { - if request.notification.is_none() { - request.notification = Some(Default::default()); - } - } - - match &temp_cursor.to_string()[..] { - "display-time" => { - request.display_time = Some(value.unwrap_or("").to_string()); - }, - "creator.kind" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "creator.display-name" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().display_name = Some(value.unwrap_or("").to_string()); - }, - "creator.accept-types" => { - request_creator_init(&mut request); - if request.creator.as_mut().unwrap().accept_types.is_none() { - request.creator.as_mut().unwrap().accept_types = Some(Default::default()); - } - request.creator.as_mut().unwrap().accept_types.as_mut().unwrap().push(value.unwrap_or("").to_string()); - }, - "creator.image-urls" => { - request_creator_init(&mut request); - if request.creator.as_mut().unwrap().image_urls.is_none() { - request.creator.as_mut().unwrap().image_urls = Some(Default::default()); - } - request.creator.as_mut().unwrap().image_urls.as_mut().unwrap().push(value.unwrap_or("").to_string()); - }, - "creator.priority" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().priority = Some(arg_from_str(value.unwrap_or("-0"), err, "creator.priority", "integer")); - }, - "creator.source" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().source = Some(value.unwrap_or("").to_string()); - }, - "creator.phone-number" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().phone_number = Some(value.unwrap_or("").to_string()); - }, - "creator.sharing-features" => { - request_creator_init(&mut request); - if request.creator.as_mut().unwrap().sharing_features.is_none() { - request.creator.as_mut().unwrap().sharing_features = Some(Default::default()); - } - request.creator.as_mut().unwrap().sharing_features.as_mut().unwrap().push(value.unwrap_or("").to_string()); - }, - "creator.type" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); - }, - "creator.id" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); - }, - "creator.speakable-name" => { - request_creator_init(&mut request); - request.creator.as_mut().unwrap().speakable_name = Some(value.unwrap_or("").to_string()); - }, - "text" => { - request_creator_init(&mut request); - request.text = Some(value.unwrap_or("").to_string()); - }, - "is-bundle-cover" => { - request_creator_init(&mut request); - request.is_bundle_cover = Some(arg_from_str(value.unwrap_or("false"), err, "is-bundle-cover", "boolean")); - }, - "etag" => { - request_creator_init(&mut request); - request.etag = Some(value.unwrap_or("").to_string()); - }, - "id" => { - request_creator_init(&mut request); - request.id = Some(value.unwrap_or("").to_string()); - }, - "is-deleted" => { - request_creator_init(&mut request); - request.is_deleted = Some(arg_from_str(value.unwrap_or("false"), err, "is-deleted", "boolean")); - }, - "bundle-id" => { - request_creator_init(&mut request); - request.bundle_id = Some(value.unwrap_or("").to_string()); - }, - "is-pinned" => { - request_creator_init(&mut request); - request.is_pinned = Some(arg_from_str(value.unwrap_or("false"), err, "is-pinned", "boolean")); - }, - "title" => { - request_creator_init(&mut request); - request.title = Some(value.unwrap_or("").to_string()); - }, - "pin-score" => { - request_creator_init(&mut request); - request.pin_score = Some(arg_from_str(value.unwrap_or("-0"), err, "pin-score", "integer")); - }, - "speakable-text" => { - request_creator_init(&mut request); - request.speakable_text = Some(value.unwrap_or("").to_string()); - }, - "html" => { - request_creator_init(&mut request); - request.html = Some(value.unwrap_or("").to_string()); - }, - "location.kind" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); - }, - "location.display-name" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().display_name = Some(value.unwrap_or("").to_string()); - }, - "location.timestamp" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().timestamp = Some(value.unwrap_or("").to_string()); - }, - "location.longitude" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().longitude = Some(arg_from_str(value.unwrap_or("0.0"), err, "location.longitude", "number")); - }, - "location.address" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().address = Some(value.unwrap_or("").to_string()); - }, - "location.latitude" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().latitude = Some(arg_from_str(value.unwrap_or("0.0"), err, "location.latitude", "number")); - }, - "location.id" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); - }, - "location.accuracy" => { - request_location_init(&mut request); - request.location.as_mut().unwrap().accuracy = Some(arg_from_str(value.unwrap_or("0.0"), err, "location.accuracy", "number")); - }, - "source-item-id" => { - request_location_init(&mut request); - request.source_item_id = Some(value.unwrap_or("").to_string()); - }, - "in-reply-to" => { - request_location_init(&mut request); - request.in_reply_to = Some(value.unwrap_or("").to_string()); - }, - "updated" => { - request_location_init(&mut request); - request.updated = Some(value.unwrap_or("").to_string()); - }, - "canonical-url" => { - request_location_init(&mut request); - request.canonical_url = Some(value.unwrap_or("").to_string()); - }, - "kind" => { - request_location_init(&mut request); - request.kind = Some(value.unwrap_or("").to_string()); - }, - "created" => { - request_location_init(&mut request); - request.created = Some(value.unwrap_or("").to_string()); - }, - "notification.level" => { - request_notification_init(&mut request); - request.notification.as_mut().unwrap().level = Some(value.unwrap_or("").to_string()); - }, - "notification.delivery-time" => { - request_notification_init(&mut request); - request.notification.as_mut().unwrap().delivery_time = Some(value.unwrap_or("").to_string()); - }, - "speakable-type" => { - request_notification_init(&mut request); - request.speakable_type = Some(value.unwrap_or("").to_string()); - }, - "self-link" => { - request_notification_init(&mut request); - request.self_link = Some(value.unwrap_or("").to_string()); - }, - _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); - } - } - } - let mut call = self.hub.timeline().update(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { - let (key, value) = parse_kv_arg(&*parg, err, false); - match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), - } - } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { - let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; - let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_accounts { - if self.opt.cmd_insert { - call_result = self._accounts_insert(dry_run, &mut err); - } else { - unreachable!(); + fn _timeline_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::TimelineItem::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_creator_init(request: &mut api::TimelineItem) { + if request.creator.is_none() { + request.creator = Some(Default::default()); + } + } + + fn request_location_init(request: &mut api::TimelineItem) { + if request.location.is_none() { + request.location = Some(Default::default()); + } + } + + fn request_notification_init(request: &mut api::TimelineItem) { + if request.notification.is_none() { + request.notification = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "display-time" => { + request.display_time = Some(value.unwrap_or("").to_string()); + }, + "creator.kind" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "creator.display-name" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().display_name = Some(value.unwrap_or("").to_string()); + }, + "creator.accept-types" => { + request_creator_init(&mut request); + if request.creator.as_mut().unwrap().accept_types.is_none() { + request.creator.as_mut().unwrap().accept_types = Some(Default::default()); + } + request.creator.as_mut().unwrap().accept_types.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "creator.image-urls" => { + request_creator_init(&mut request); + if request.creator.as_mut().unwrap().image_urls.is_none() { + request.creator.as_mut().unwrap().image_urls = Some(Default::default()); + } + request.creator.as_mut().unwrap().image_urls.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "creator.priority" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().priority = Some(arg_from_str(value.unwrap_or("-0"), err, "creator.priority", "integer")); + }, + "creator.source" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().source = Some(value.unwrap_or("").to_string()); + }, + "creator.phone-number" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().phone_number = Some(value.unwrap_or("").to_string()); + }, + "creator.sharing-features" => { + request_creator_init(&mut request); + if request.creator.as_mut().unwrap().sharing_features.is_none() { + request.creator.as_mut().unwrap().sharing_features = Some(Default::default()); + } + request.creator.as_mut().unwrap().sharing_features.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "creator.type" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); + }, + "creator.id" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "creator.speakable-name" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().speakable_name = Some(value.unwrap_or("").to_string()); + }, + "text" => { + request_creator_init(&mut request); + request.text = Some(value.unwrap_or("").to_string()); + }, + "is-bundle-cover" => { + request_creator_init(&mut request); + request.is_bundle_cover = Some(arg_from_str(value.unwrap_or("false"), err, "is-bundle-cover", "boolean")); + }, + "etag" => { + request_creator_init(&mut request); + request.etag = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_creator_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "is-deleted" => { + request_creator_init(&mut request); + request.is_deleted = Some(arg_from_str(value.unwrap_or("false"), err, "is-deleted", "boolean")); + }, + "bundle-id" => { + request_creator_init(&mut request); + request.bundle_id = Some(value.unwrap_or("").to_string()); + }, + "is-pinned" => { + request_creator_init(&mut request); + request.is_pinned = Some(arg_from_str(value.unwrap_or("false"), err, "is-pinned", "boolean")); + }, + "title" => { + request_creator_init(&mut request); + request.title = Some(value.unwrap_or("").to_string()); + }, + "pin-score" => { + request_creator_init(&mut request); + request.pin_score = Some(arg_from_str(value.unwrap_or("-0"), err, "pin-score", "integer")); + }, + "speakable-text" => { + request_creator_init(&mut request); + request.speakable_text = Some(value.unwrap_or("").to_string()); + }, + "html" => { + request_creator_init(&mut request); + request.html = Some(value.unwrap_or("").to_string()); + }, + "location.kind" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "location.display-name" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().display_name = Some(value.unwrap_or("").to_string()); + }, + "location.timestamp" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().timestamp = Some(value.unwrap_or("").to_string()); + }, + "location.longitude" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().longitude = Some(arg_from_str(value.unwrap_or("0.0"), err, "location.longitude", "number")); + }, + "location.address" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().address = Some(value.unwrap_or("").to_string()); + }, + "location.latitude" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().latitude = Some(arg_from_str(value.unwrap_or("0.0"), err, "location.latitude", "number")); + }, + "location.id" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "location.accuracy" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().accuracy = Some(arg_from_str(value.unwrap_or("0.0"), err, "location.accuracy", "number")); + }, + "source-item-id" => { + request_location_init(&mut request); + request.source_item_id = Some(value.unwrap_or("").to_string()); + }, + "in-reply-to" => { + request_location_init(&mut request); + request.in_reply_to = Some(value.unwrap_or("").to_string()); + }, + "updated" => { + request_location_init(&mut request); + request.updated = Some(value.unwrap_or("").to_string()); + }, + "canonical-url" => { + request_location_init(&mut request); + request.canonical_url = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_location_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "created" => { + request_location_init(&mut request); + request.created = Some(value.unwrap_or("").to_string()); + }, + "notification.level" => { + request_notification_init(&mut request); + request.notification.as_mut().unwrap().level = Some(value.unwrap_or("").to_string()); + }, + "notification.delivery-time" => { + request_notification_init(&mut request); + request.notification.as_mut().unwrap().delivery_time = Some(value.unwrap_or("").to_string()); + }, + "speakable-type" => { + request_notification_init(&mut request); + request.speakable_type = Some(value.unwrap_or("").to_string()); + }, + "self-link" => { + request_notification_init(&mut request); + request.self_link = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["accept-types", "accuracy", "address", "bundle-id", "canonical-url", "created", "creator", "delivery-time", "display-name", "display-time", "etag", "html", "id", "image-urls", "in-reply-to", "is-bundle-cover", "is-deleted", "is-pinned", "kind", "latitude", "level", "location", "longitude", "notification", "phone-number", "pin-score", "priority", "self-link", "sharing-features", "source", "source-item-id", "speakable-name", "speakable-text", "speakable-type", "text", "timestamp", "title", "type", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } } } - else if self.opt.cmd_contacts { - if self.opt.cmd_delete { - call_result = self._contacts_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._contacts_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._contacts_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._contacts_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._contacts_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._contacts_update(dry_run, &mut err); - } else { - unreachable!(); + let mut call = self.hub.timeline().patch(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - else if self.opt.cmd_locations { - if self.opt.cmd_get { - call_result = self._locations_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._locations_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_settings { - if self.opt.cmd_get { - call_result = self._settings_get(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_subscriptions { - if self.opt.cmd_delete { - call_result = self._subscriptions_delete(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._subscriptions_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._subscriptions_list(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._subscriptions_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_timeline { - if self.opt.cmd_attachments_delete { - call_result = self._timeline_attachments_delete(dry_run, &mut err); - } else if self.opt.cmd_attachments_get { - call_result = self._timeline_attachments_get(dry_run, &mut err); - } else if self.opt.cmd_attachments_insert { - call_result = self._timeline_attachments_insert(dry_run, &mut err); - } else if self.opt.cmd_attachments_list { - call_result = self._timeline_attachments_list(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._timeline_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._timeline_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._timeline_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._timeline_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._timeline_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._timeline_update(dry_run, &mut err); - } else { - unreachable!(); - } + let protocol = CallType::Standard; + if dry_run { + Ok(()) } else { - unreachable!(); + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Standard => call.doit(), + _ => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _timeline_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + + let mut request = api::TimelineItem::default(); + let mut field_cursor = FieldCursor::default(); + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { + let last_errc = err.issues.len(); + let (key, value) = parse_kv_arg(&*kvarg, err, false); + let mut temp_cursor = field_cursor.clone(); + if let Err(field_err) = temp_cursor.set(&*key) { + err.issues.push(field_err); + } + if value.is_none() { + field_cursor = temp_cursor.clone(); + if err.issues.len() > last_errc { + err.issues.remove(last_errc); + } + continue; + } + fn request_creator_init(request: &mut api::TimelineItem) { + if request.creator.is_none() { + request.creator = Some(Default::default()); + } + } + + fn request_location_init(request: &mut api::TimelineItem) { + if request.location.is_none() { + request.location = Some(Default::default()); + } + } + + fn request_notification_init(request: &mut api::TimelineItem) { + if request.notification.is_none() { + request.notification = Some(Default::default()); + } + } + + match &temp_cursor.to_string()[..] { + "display-time" => { + request.display_time = Some(value.unwrap_or("").to_string()); + }, + "creator.kind" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "creator.display-name" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().display_name = Some(value.unwrap_or("").to_string()); + }, + "creator.accept-types" => { + request_creator_init(&mut request); + if request.creator.as_mut().unwrap().accept_types.is_none() { + request.creator.as_mut().unwrap().accept_types = Some(Default::default()); + } + request.creator.as_mut().unwrap().accept_types.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "creator.image-urls" => { + request_creator_init(&mut request); + if request.creator.as_mut().unwrap().image_urls.is_none() { + request.creator.as_mut().unwrap().image_urls = Some(Default::default()); + } + request.creator.as_mut().unwrap().image_urls.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "creator.priority" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().priority = Some(arg_from_str(value.unwrap_or("-0"), err, "creator.priority", "integer")); + }, + "creator.source" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().source = Some(value.unwrap_or("").to_string()); + }, + "creator.phone-number" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().phone_number = Some(value.unwrap_or("").to_string()); + }, + "creator.sharing-features" => { + request_creator_init(&mut request); + if request.creator.as_mut().unwrap().sharing_features.is_none() { + request.creator.as_mut().unwrap().sharing_features = Some(Default::default()); + } + request.creator.as_mut().unwrap().sharing_features.as_mut().unwrap().push(value.unwrap_or("").to_string()); + }, + "creator.type" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); + }, + "creator.id" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "creator.speakable-name" => { + request_creator_init(&mut request); + request.creator.as_mut().unwrap().speakable_name = Some(value.unwrap_or("").to_string()); + }, + "text" => { + request_creator_init(&mut request); + request.text = Some(value.unwrap_or("").to_string()); + }, + "is-bundle-cover" => { + request_creator_init(&mut request); + request.is_bundle_cover = Some(arg_from_str(value.unwrap_or("false"), err, "is-bundle-cover", "boolean")); + }, + "etag" => { + request_creator_init(&mut request); + request.etag = Some(value.unwrap_or("").to_string()); + }, + "id" => { + request_creator_init(&mut request); + request.id = Some(value.unwrap_or("").to_string()); + }, + "is-deleted" => { + request_creator_init(&mut request); + request.is_deleted = Some(arg_from_str(value.unwrap_or("false"), err, "is-deleted", "boolean")); + }, + "bundle-id" => { + request_creator_init(&mut request); + request.bundle_id = Some(value.unwrap_or("").to_string()); + }, + "is-pinned" => { + request_creator_init(&mut request); + request.is_pinned = Some(arg_from_str(value.unwrap_or("false"), err, "is-pinned", "boolean")); + }, + "title" => { + request_creator_init(&mut request); + request.title = Some(value.unwrap_or("").to_string()); + }, + "pin-score" => { + request_creator_init(&mut request); + request.pin_score = Some(arg_from_str(value.unwrap_or("-0"), err, "pin-score", "integer")); + }, + "speakable-text" => { + request_creator_init(&mut request); + request.speakable_text = Some(value.unwrap_or("").to_string()); + }, + "html" => { + request_creator_init(&mut request); + request.html = Some(value.unwrap_or("").to_string()); + }, + "location.kind" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().kind = Some(value.unwrap_or("").to_string()); + }, + "location.display-name" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().display_name = Some(value.unwrap_or("").to_string()); + }, + "location.timestamp" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().timestamp = Some(value.unwrap_or("").to_string()); + }, + "location.longitude" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().longitude = Some(arg_from_str(value.unwrap_or("0.0"), err, "location.longitude", "number")); + }, + "location.address" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().address = Some(value.unwrap_or("").to_string()); + }, + "location.latitude" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().latitude = Some(arg_from_str(value.unwrap_or("0.0"), err, "location.latitude", "number")); + }, + "location.id" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().id = Some(value.unwrap_or("").to_string()); + }, + "location.accuracy" => { + request_location_init(&mut request); + request.location.as_mut().unwrap().accuracy = Some(arg_from_str(value.unwrap_or("0.0"), err, "location.accuracy", "number")); + }, + "source-item-id" => { + request_location_init(&mut request); + request.source_item_id = Some(value.unwrap_or("").to_string()); + }, + "in-reply-to" => { + request_location_init(&mut request); + request.in_reply_to = Some(value.unwrap_or("").to_string()); + }, + "updated" => { + request_location_init(&mut request); + request.updated = Some(value.unwrap_or("").to_string()); + }, + "canonical-url" => { + request_location_init(&mut request); + request.canonical_url = Some(value.unwrap_or("").to_string()); + }, + "kind" => { + request_location_init(&mut request); + request.kind = Some(value.unwrap_or("").to_string()); + }, + "created" => { + request_location_init(&mut request); + request.created = Some(value.unwrap_or("").to_string()); + }, + "notification.level" => { + request_notification_init(&mut request); + request.notification.as_mut().unwrap().level = Some(value.unwrap_or("").to_string()); + }, + "notification.delivery-time" => { + request_notification_init(&mut request); + request.notification.as_mut().unwrap().delivery_time = Some(value.unwrap_or("").to_string()); + }, + "speakable-type" => { + request_notification_init(&mut request); + request.speakable_type = Some(value.unwrap_or("").to_string()); + }, + "self-link" => { + request_notification_init(&mut request); + request.self_link = Some(value.unwrap_or("").to_string()); + }, + _ => { + let suggestion = FieldCursor::did_you_mean(key, &vec!["accept-types", "accuracy", "address", "bundle-id", "canonical-url", "created", "creator", "delivery-time", "display-name", "display-time", "etag", "html", "id", "image-urls", "in-reply-to", "is-bundle-cover", "is-deleted", "is-pinned", "kind", "latitude", "level", "location", "longitude", "notification", "phone-number", "pin-score", "priority", "self-link", "sharing-features", "source", "source-item-id", "speakable-name", "speakable-text", "speakable-type", "text", "timestamp", "title", "type", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); + } + } + } + let mut call = self.hub.timeline().update(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { + let (key, value) = parse_kv_arg(&*parg, err, false); + match key { + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } + } + } + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; + match match protocol { + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() + } { + Err(api_err) => Err(DoitError::ApiError(api_err)), + Ok((mut response, output_schema)) => { + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) + } + } + } + } + + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { + let mut err = InvalidOptionsError::new(); + let mut call_result: Result<(), DoitError> = Ok(()); + let mut err_opt: Option<InvalidOptionsError> = None; + match self.opt.subcommand() { + ("accounts", Some(opt)) => { + match opt.subcommand() { + ("insert", Some(opt)) => { + call_result = self._accounts_insert(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("accounts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("contacts", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._contacts_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._contacts_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._contacts_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._contacts_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._contacts_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._contacts_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("contacts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("locations", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._locations_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._locations_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("locations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("settings", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._settings_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("settings".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("subscriptions", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._subscriptions_delete(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._subscriptions_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._subscriptions_list(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._subscriptions_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("subscriptions".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("timeline", Some(opt)) => { + match opt.subcommand() { + ("attachments-delete", Some(opt)) => { + call_result = self._timeline_attachments_delete(opt, dry_run, &mut err); + }, + ("attachments-get", Some(opt)) => { + call_result = self._timeline_attachments_get(opt, dry_run, &mut err); + }, + ("attachments-insert", Some(opt)) => { + call_result = self._timeline_attachments_insert(opt, dry_run, &mut err); + }, + ("attachments-list", Some(opt)) => { + call_result = self._timeline_attachments_list(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._timeline_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._timeline_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._timeline_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._timeline_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._timeline_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._timeline_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("timeline".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); + } } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -2376,7 +2453,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2389,7 +2466,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -2399,37 +2476,713 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Mirror::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let upload_value_names = ["mode", "file"]; + let arg_data = [ + ("accounts", "methods: 'insert'", vec![ + ("insert", + Some(r##"Inserts a new account for a user"##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/accounts_insert", + vec![ + (Some(r##"user-token"##), + None, + Some(r##"The ID for the user."##), + Some(true), + Some(false)), + + (Some(r##"account-type"##), + None, + Some(r##"Account type to be passed to Android Account Manager."##), + Some(true), + Some(false)), + + (Some(r##"account-name"##), + None, + Some(r##"The name of the account to be passed to the Android Account Manager."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("contacts", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes a contact."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/contacts_delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the contact."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets a single contact by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/contacts_get", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the contact."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new contact."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/contacts_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of contacts for the authenticated user."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/contacts_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a contact in place. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/contacts_patch", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the contact."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a contact in place."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/contacts_update", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the contact."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("locations", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Gets a single location by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/locations_get", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the location or latest for the last known location."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of locations for the user."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/locations_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("settings", "methods: 'get'", vec![ + ("get", + Some(r##"Gets a single setting by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/settings_get", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the setting. The following IDs are valid: + - locale - The key to the user’s language/locale (BCP 47 identifier) that Glassware should use to render localized content. + - timezone - The key to the user’s current time zone region as defined in the tz database. Example: America/Los_Angeles."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("subscriptions", "methods: 'delete', 'insert', 'list' and 'update'", vec![ + ("delete", + Some(r##"Deletes a subscription."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/subscriptions_delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the subscription."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("insert", + Some(r##"Creates a new subscription."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/subscriptions_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of subscriptions for the authenticated user and service."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/subscriptions_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing subscription in place."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/subscriptions_update", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the subscription."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("timeline", "methods: 'attachments-delete', 'attachments-get', 'attachments-insert', 'attachments-list', 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("attachments-delete", + Some(r##"Deletes an attachment from a timeline item."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/timeline_attachments-delete", + vec![ + (Some(r##"item-id"##), + None, + Some(r##"The ID of the timeline item the attachment belongs to."##), + Some(true), + Some(false)), + + (Some(r##"attachment-id"##), + None, + Some(r##"The ID of the attachment."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("attachments-get", + Some(r##"Retrieves an attachment on a timeline item by item ID and attachment ID."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/timeline_attachments-get", + vec![ + (Some(r##"item-id"##), + None, + Some(r##"The ID of the timeline item the attachment belongs to."##), + Some(true), + Some(false)), + + (Some(r##"attachment-id"##), + None, + Some(r##"The ID of the attachment."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("attachments-insert", + Some(r##"Adds a new attachment to a timeline item."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/timeline_attachments-insert", + vec![ + (Some(r##"item-id"##), + None, + Some(r##"The ID of the timeline item the attachment belongs to."##), + Some(true), + Some(false)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("attachments-list", + Some(r##"Returns a list of attachments for a timeline item."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/timeline_attachments-list", + vec![ + (Some(r##"item-id"##), + None, + Some(r##"The ID of the timeline item whose attachments should be listed."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes a timeline item."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/timeline_delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the timeline item."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets a single timeline item by ID."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/timeline_get", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the timeline item."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a new item into the timeline."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/timeline_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of timeline items for the authenticated user."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/timeline_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a timeline item in place. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/timeline_patch", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the timeline item."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a timeline item in place."##), + "Details at http://byron.github.io/google-apis-rs/google_mirror1_cli/timeline_update", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the timeline item."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("mirror1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150220") + .about("API for interacting with Glass users via the timeline.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_mirror1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + if arg_name_str == "mode" { + arg = arg.number_of_values(2); + arg = arg.value_names(&upload_value_names); + + scmd = scmd.arg(Arg::with_name("mime") + .short("m") + .requires("mode") + .required(false) + .help("The file's mime time, like 'application/octet-stream'") + .takes_value(true)); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/mirror1/Cargo.toml b/gen/mirror1/Cargo.toml index 424257bf08..69ca089d9e 100644 --- a/gen/mirror1/Cargo.toml +++ b/gen/mirror1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-mirror1" -version = "0.1.6+20150220" +version = "0.1.7+20150220" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with mirror (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/mirror1" @@ -15,9 +15,10 @@ keywords = ["mirror", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/mirror1/README.md b/gen/mirror1/README.md index 06b4f0c961..5b3b99d4fd 100644 --- a/gen/mirror1/README.md +++ b/gen/mirror1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-mirror1` library allows access to all features of the *Google mirror* service. -This documentation was generated from *mirror* crate version *0.1.6+20150220*, where *20150220* is the exact revision of the *mirror:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *mirror* crate version *0.1.7+20150220*, where *20150220* is the exact revision of the *mirror:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *mirror* *v1* API can be found at the [official documentation site](https://developers.google.com/glass). @@ -188,7 +188,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_mirror1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_mirror1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/mirror1/src/cmn.rs b/gen/mirror1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/mirror1/src/cmn.rs +++ b/gen/mirror1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/mirror1/src/lib.rs b/gen/mirror1/src/lib.rs index 5e71e5d889..4e84e6c400 100644 --- a/gen/mirror1/src/lib.rs +++ b/gen/mirror1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *mirror* crate version *0.1.6+20150220*, where *20150220* is the exact revision of the *mirror:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *mirror* crate version *0.1.7+20150220*, where *20150220* is the exact revision of the *mirror:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *mirror* *v1* API can be found at the //! [official documentation site](https://developers.google.com/glass). @@ -189,7 +189,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -198,7 +198,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -214,6 +213,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -340,7 +340,7 @@ impl<'a, C, A> Mirror<C, A> Mirror { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -364,7 +364,7 @@ impl<'a, C, A> Mirror<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1729,6 +1729,7 @@ impl<'a, C, A> SubscriptionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Subscription)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1759,11 +1760,20 @@ impl<'a, C, A> SubscriptionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1786,7 +1796,7 @@ impl<'a, C, A> SubscriptionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2004,7 +2014,7 @@ impl<'a, C, A> SubscriptionDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2026,7 +2036,7 @@ impl<'a, C, A> SubscriptionDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2185,6 +2195,7 @@ impl<'a, C, A> SubscriptionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Subscription)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2240,11 +2251,20 @@ impl<'a, C, A> SubscriptionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2267,7 +2287,7 @@ impl<'a, C, A> SubscriptionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2470,7 +2490,7 @@ impl<'a, C, A> SubscriptionListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2492,7 +2512,7 @@ impl<'a, C, A> SubscriptionListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2699,7 +2719,7 @@ impl<'a, C, A> TimelineAttachmentListCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2721,7 +2741,7 @@ impl<'a, C, A> TimelineAttachmentListCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2891,6 +2911,7 @@ impl<'a, C, A> TimelineInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, TimelineItem)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2929,11 +2950,20 @@ impl<'a, C, A> TimelineInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2988,7 +3018,7 @@ impl<'a, C, A> TimelineInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A _ => (&mut request_value_reader as &mut io::Read, ContentType(json_mime_type.clone())), }; let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(content_type) @@ -3038,7 +3068,7 @@ impl<'a, C, A> TimelineInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -3066,6 +3096,7 @@ impl<'a, C, A> TimelineInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -3233,6 +3264,7 @@ impl<'a, C, A> TimelinePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, TimelineItem)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3288,11 +3320,20 @@ impl<'a, C, A> TimelinePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3315,7 +3356,7 @@ impl<'a, C, A> TimelinePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3553,7 +3594,7 @@ impl<'a, C, A> TimelineListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3575,7 +3616,7 @@ impl<'a, C, A> TimelineListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3841,7 +3882,7 @@ impl<'a, C, A> TimelineAttachmentInsertCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3879,7 +3920,7 @@ impl<'a, C, A> TimelineAttachmentInsertCall<'a, C, A> where C: BorrowMut<hyper:: response } else { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); if protocol == "simple" { @@ -3937,7 +3978,7 @@ impl<'a, C, A> TimelineAttachmentInsertCall<'a, C, A> where C: BorrowMut<hyper:: let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -3965,6 +4006,7 @@ impl<'a, C, A> TimelineAttachmentInsertCall<'a, C, A> where C: BorrowMut<hyper:: Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -4182,7 +4224,7 @@ impl<'a, C, A> TimelineAttachmentDeleteCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4204,7 +4246,7 @@ impl<'a, C, A> TimelineAttachmentDeleteCall<'a, C, A> where C: BorrowMut<hyper:: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4420,7 +4462,7 @@ impl<'a, C, A> TimelineDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4442,7 +4484,7 @@ impl<'a, C, A> TimelineDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4603,6 +4645,7 @@ impl<'a, C, A> TimelineUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, TimelineItem)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4666,11 +4709,20 @@ impl<'a, C, A> TimelineUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4725,7 +4777,7 @@ impl<'a, C, A> TimelineUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A _ => (&mut request_value_reader as &mut io::Read, ContentType(json_mime_type.clone())), }; let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(content_type) @@ -4775,7 +4827,7 @@ impl<'a, C, A> TimelineUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -4803,6 +4855,7 @@ impl<'a, C, A> TimelineUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -5051,7 +5104,7 @@ impl<'a, C, A> TimelineAttachmentGetCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5073,7 +5126,7 @@ impl<'a, C, A> TimelineAttachmentGetCall<'a, C, A> where C: BorrowMut<hyper::Cli access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5300,7 +5353,7 @@ impl<'a, C, A> TimelineGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5322,7 +5375,7 @@ impl<'a, C, A> TimelineGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5539,7 +5592,7 @@ impl<'a, C, A> SettingGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5561,7 +5614,7 @@ impl<'a, C, A> SettingGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5780,7 +5833,7 @@ impl<'a, C, A> LocationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5802,7 +5855,7 @@ impl<'a, C, A> LocationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5993,7 +6046,7 @@ impl<'a, C, A> LocationListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6015,7 +6068,7 @@ impl<'a, C, A> LocationListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6175,6 +6228,7 @@ impl<'a, C, A> AccountInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Account)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6241,11 +6295,20 @@ impl<'a, C, A> AccountInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6254,7 +6317,7 @@ impl<'a, C, A> AccountInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -6486,7 +6549,7 @@ impl<'a, C, A> ContactGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6508,7 +6571,7 @@ impl<'a, C, A> ContactGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6724,7 +6787,7 @@ impl<'a, C, A> ContactDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6746,7 +6809,7 @@ impl<'a, C, A> ContactDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6904,6 +6967,7 @@ impl<'a, C, A> ContactInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Contact)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6934,11 +6998,20 @@ impl<'a, C, A> ContactInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6961,7 +7034,7 @@ impl<'a, C, A> ContactInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7132,6 +7205,7 @@ impl<'a, C, A> ContactPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Contact)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7187,11 +7261,20 @@ impl<'a, C, A> ContactPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7214,7 +7297,7 @@ impl<'a, C, A> ContactPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7417,7 +7500,7 @@ impl<'a, C, A> ContactListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7439,7 +7522,7 @@ impl<'a, C, A> ContactListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7598,6 +7681,7 @@ impl<'a, C, A> ContactUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Contact)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7653,11 +7737,20 @@ impl<'a, C, A> ContactUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7680,7 +7773,7 @@ impl<'a, C, A> ContactUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) diff --git a/gen/oauth2_v2-cli/Cargo.toml b/gen/oauth2_v2-cli/Cargo.toml index 8ef9be7c49..5d8d108239 100644 --- a/gen/oauth2_v2-cli/Cargo.toml +++ b/gen/oauth2_v2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-oauth2_v2-cli" -version = "0.1.0+20150416" +version = "0.2.0+20150416" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with oauth2 (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/oauth2_v2-cli" @@ -17,15 +17,14 @@ keywords = ["oauth2", "google", "cli"] name = "oauth2-v2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-oauth2_v2] path = "../oauth2_v2" diff --git a/gen/oauth2_v2-cli/README.md b/gen/oauth2_v2-cli/README.md index 52569ecb8a..cf32248b9f 100644 --- a/gen/oauth2_v2-cli/README.md +++ b/gen/oauth2_v2-cli/README.md @@ -10,24 +10,27 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *oauth2* API can be found at the +[official documentation site](https://developers.google.com/accounts/docs/OAuth2). + # Usage -This documentation was generated from the *oauth2* API at revision *20150416*. The CLI is at version *0.1.0*. +This documentation was generated from the *oauth2* API at revision *20150416*. The CLI is at version *0.2.0*. ```bash - oauth2-v2 [options] methods get-cert-for-open-id-connect [-p <v>...] [-o <out>] - oauth2-v2 [options] methods tokeninfo [-p <v>...] [-o <out>] - oauth2-v2 [options] userinfo get [-p <v>...] [-o <out>] - oauth2-v2 [options] userinfo v2-me-get [-p <v>...] [-o <out>] +oauth2-v2 [options] + methods + get-cert-for-open-id-connect [-p <v>]... [-o <out>] + tokeninfo [-p <v>]... [-o <out>] + userinfo + get [-p <v>]... [-o <out>] + v2-me-get [-p <v>]... [-o <out>] oauth2-v2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_oauth2_v2_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/oauth2_v2-cli/mkdocs.yml b/gen/oauth2_v2-cli/mkdocs.yml index e2dee89956..5bfdbca14c 100644 --- a/gen/oauth2_v2-cli/mkdocs.yml +++ b/gen/oauth2_v2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: oauth2 v0.1.0+20150416 +site_name: oauth2 v0.2.0+20150416 site_url: http://byron.github.io/google-apis-rs/google-oauth2_v2-cli site_description: Write integrating applications with bcore diff --git a/gen/oauth2_v2-cli/src/cmn.rs b/gen/oauth2_v2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/oauth2_v2-cli/src/cmn.rs +++ b/gen/oauth2_v2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/oauth2_v2-cli/src/main.rs b/gen/oauth2_v2-cli/src/main.rs index dca65268c2..1c4cd4c87e 100644 --- a/gen/oauth2_v2-cli/src/main.rs +++ b/gen/oauth2_v2-cli/src/main.rs @@ -2,113 +2,100 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_oauth2_v2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - oauth2-v2 [options] methods get-cert-for-open-id-connect [-p <v>...] [-o <out>] - oauth2-v2 [options] methods tokeninfo [-p <v>...] [-o <out>] - oauth2-v2 [options] userinfo get [-p <v>...] [-o <out>] - oauth2-v2 [options] userinfo v2-me-get [-p <v>...] [-o <out>] - oauth2-v2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_oauth2_v2_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Oauth2<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _methods_get_cert_for_open_id_connect(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _methods_get_cert_for_open_id_connect(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.methods().get_cert_for_open_id_connect(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _methods_tokeninfo(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _methods_tokeninfo(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.methods().tokeninfo(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "token-handle" => { @@ -120,173 +107,200 @@ impl Engine { "access-token" => { call = call.access_token(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["access-token", "id-token", "token-handle"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _userinfo_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _userinfo_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.userinfo().get(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _userinfo_v2_me_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _userinfo_v2_me_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.userinfo().v2_me_get(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_methods { - if self.opt.cmd_get_cert_for_open_id_connect { - call_result = self._methods_get_cert_for_open_id_connect(dry_run, &mut err); - } else if self.opt.cmd_tokeninfo { - call_result = self._methods_tokeninfo(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("methods", Some(opt)) => { + match opt.subcommand() { + ("get-cert-for-open-id-connect", Some(opt)) => { + call_result = self._methods_get_cert_for_open_id_connect(opt, dry_run, &mut err); + }, + ("tokeninfo", Some(opt)) => { + call_result = self._methods_tokeninfo(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("methods".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("userinfo", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._userinfo_get(opt, dry_run, &mut err); + }, + ("v2-me-get", Some(opt)) => { + call_result = self._userinfo_v2_me_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("userinfo".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_userinfo { - if self.opt.cmd_get { - call_result = self._userinfo_get(dry_run, &mut err); - } else if self.opt.cmd_v2_me_get { - call_result = self._userinfo_v2_me_get(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -299,7 +313,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -312,7 +326,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -322,37 +336,193 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Oauth2::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("methods", "methods: 'get-cert-for-open-id-connect' and 'tokeninfo'", vec![ + ("get-cert-for-open-id-connect", + None, + "Details at http://byron.github.io/google-apis-rs/google_oauth2_v2_cli/methods_get-cert-for-open-id-connect", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("tokeninfo", + None, + "Details at http://byron.github.io/google-apis-rs/google_oauth2_v2_cli/methods_tokeninfo", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("userinfo", "methods: 'get' and 'v2-me-get'", vec![ + ("get", + None, + "Details at http://byron.github.io/google-apis-rs/google_oauth2_v2_cli/userinfo_get", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("v2-me-get", + None, + "Details at http://byron.github.io/google-apis-rs/google_oauth2_v2_cli/userinfo_v2-me-get", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("oauth2-v2") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150416") + .about("Lets you access OAuth2 protocol related APIs.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_oauth2_v2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/oauth2_v2/Cargo.toml b/gen/oauth2_v2/Cargo.toml index 873512b778..250927e404 100644 --- a/gen/oauth2_v2/Cargo.toml +++ b/gen/oauth2_v2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-oauth2_v2" -version = "0.1.6+20150416" +version = "0.1.7+20150416" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with oauth2 (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/oauth2_v2" @@ -15,9 +15,10 @@ keywords = ["oauth2", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/oauth2_v2/README.md b/gen/oauth2_v2/README.md index 0f62b458e5..d2d766f1ae 100644 --- a/gen/oauth2_v2/README.md +++ b/gen/oauth2_v2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-oauth2_v2` library allows access to all features of the *Google oauth2* service. -This documentation was generated from *oauth2* crate version *0.1.6+20150416*, where *20150416* is the exact revision of the *oauth2:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *oauth2* crate version *0.1.7+20150416*, where *20150416* is the exact revision of the *oauth2:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *oauth2* *v2* API can be found at the [official documentation site](https://developers.google.com/accounts/docs/OAuth2). @@ -162,7 +162,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_oauth2_v2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_oauth2_v2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/oauth2_v2/src/cmn.rs b/gen/oauth2_v2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/oauth2_v2/src/cmn.rs +++ b/gen/oauth2_v2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/oauth2_v2/src/lib.rs b/gen/oauth2_v2/src/lib.rs index 6a2f8e33cc..e9bb05c4e8 100644 --- a/gen/oauth2_v2/src/lib.rs +++ b/gen/oauth2_v2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *oauth2* crate version *0.1.6+20150416*, where *20150416* is the exact revision of the *oauth2:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *oauth2* crate version *0.1.7+20150416*, where *20150416* is the exact revision of the *oauth2:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *oauth2* *v2* API can be found at the //! [official documentation site](https://developers.google.com/accounts/docs/OAuth2). @@ -163,7 +163,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -172,7 +172,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -188,6 +187,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -316,7 +316,7 @@ impl<'a, C, A> Oauth2<C, A> Oauth2 { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -328,7 +328,7 @@ impl<'a, C, A> Oauth2<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -662,7 +662,7 @@ impl<'a, C, A> UserinfoV2MeGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -684,7 +684,7 @@ impl<'a, C, A> UserinfoV2MeGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -863,7 +863,7 @@ impl<'a, C, A> UserinfoGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -885,7 +885,7 @@ impl<'a, C, A> UserinfoGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1087,7 +1087,7 @@ impl<'a, C, A> MethodTokeninfoCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1095,7 +1095,7 @@ impl<'a, C, A> MethodTokeninfoCall<'a, C, A> where C: BorrowMut<hyper::Client>, loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -1283,7 +1283,7 @@ impl<'a, C, A> MethodGetCertForOpenIdConnectCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1291,7 +1291,7 @@ impl<'a, C, A> MethodGetCertForOpenIdConnectCall<'a, C, A> where C: BorrowMut<hy loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); diff --git a/gen/pagespeedonline2-cli/Cargo.toml b/gen/pagespeedonline2-cli/Cargo.toml index e2ab450d70..fe6f9d41d7 100644 --- a/gen/pagespeedonline2-cli/Cargo.toml +++ b/gen/pagespeedonline2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-pagespeedonline2-cli" -version = "0.1.0+20150317" +version = "0.2.0+20150317" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with pagespeedonline (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/pagespeedonline2-cli" @@ -17,15 +17,14 @@ keywords = ["pagespeedonline", "google", "cli"] name = "pagespeedonline2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-pagespeedonline2] path = "../pagespeedonline2" diff --git a/gen/pagespeedonline2-cli/README.md b/gen/pagespeedonline2-cli/README.md index d384c56065..96c3954087 100644 --- a/gen/pagespeedonline2-cli/README.md +++ b/gen/pagespeedonline2-cli/README.md @@ -10,17 +10,19 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *pagespeedonline* API can be found at the +[official documentation site](https://developers.google.com/speed/docs/insights/v2/getting-started). + # Usage -This documentation was generated from the *pagespeedonline* API at revision *20150317*. The CLI is at version *0.1.0*. +This documentation was generated from the *pagespeedonline* API at revision *20150317*. The CLI is at version *0.2.0*. ```bash - pagespeedonline2 [options] pagespeedapi runpagespeed <url> [-p <v>...] [-o <out>] +pagespeedonline2 [options] + pagespeedapi + runpagespeed <url> [-p <v>]... [-o <out>] pagespeedonline2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_pagespeedonline2_cli/index.html - Configuration: --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/pagespeedonline2-cli/mkdocs.yml b/gen/pagespeedonline2-cli/mkdocs.yml index 9e2345d4ff..844b5784a0 100644 --- a/gen/pagespeedonline2-cli/mkdocs.yml +++ b/gen/pagespeedonline2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: pagespeedonline v0.1.0+20150317 +site_name: pagespeedonline v0.2.0+20150317 site_url: http://byron.github.io/google-apis-rs/google-pagespeedonline2-cli site_description: Write integrating applications with bcore diff --git a/gen/pagespeedonline2-cli/src/cmn.rs b/gen/pagespeedonline2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/pagespeedonline2-cli/src/cmn.rs +++ b/gen/pagespeedonline2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/pagespeedonline2-cli/src/main.rs b/gen/pagespeedonline2-cli/src/main.rs index 9b77b1ba0f..1a07dfe09c 100644 --- a/gen/pagespeedonline2-cli/src/main.rs +++ b/gen/pagespeedonline2-cli/src/main.rs @@ -2,63 +2,53 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_pagespeedonline2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - pagespeedonline2 [options] pagespeedapi runpagespeed <url> [-p <v>...] [-o <out>] - pagespeedonline2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_pagespeedonline2_cli/index.html - -Configuration: - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Pagespeedonline<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _pagespeedapi_runpagespeed(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.pagespeedapi().runpagespeed(&self.opt.arg_url); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _pagespeedapi_runpagespeed(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.pagespeedapi().runpagespeed(opt.value_of("url").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "strategy" => { @@ -76,70 +66,83 @@ impl Engine { "filter-third-party-resources" => { call = call.filter_third_party_resources(arg_from_str(value.unwrap_or("false"), err, "filter-third-party-resources", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["locale", "filter-third-party-resources", "rule", "screenshot", "strategy"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_pagespeedapi { - if self.opt.cmd_runpagespeed { - call_result = self._pagespeedapi_runpagespeed(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("pagespeedapi", Some(opt)) => { + match opt.subcommand() { + ("runpagespeed", Some(opt)) => { + call_result = self._pagespeedapi_runpagespeed(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("pagespeedapi".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -152,7 +155,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -165,7 +168,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -175,37 +178,143 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Pagespeedonline::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("pagespeedapi", "methods: 'runpagespeed'", vec![ + ("runpagespeed", + Some(r##"Runs PageSpeed analysis on the page at the specified URL, and returns PageSpeed scores, a list of suggestions to make that page faster, and other information."##), + "Details at http://byron.github.io/google-apis-rs/google_pagespeedonline2_cli/pagespeedapi_runpagespeed", + vec![ + (Some(r##"url"##), + None, + Some(r##"The URL to fetch and analyze"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("pagespeedonline2") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150317") + .about("Lets you analyze the performance of a web page and get tailored suggestions to make that page faster.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_pagespeedonline2_cli") + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/pagespeedonline2/Cargo.toml b/gen/pagespeedonline2/Cargo.toml index a0dfca69f3..fd0deed512 100644 --- a/gen/pagespeedonline2/Cargo.toml +++ b/gen/pagespeedonline2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-pagespeedonline2" -version = "0.1.6+20150317" +version = "0.1.7+20150317" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with pagespeedonline (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/pagespeedonline2" @@ -15,9 +15,10 @@ keywords = ["pagespeedonline", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/pagespeedonline2/README.md b/gen/pagespeedonline2/README.md index bb7a5ffc38..a4e2d73299 100644 --- a/gen/pagespeedonline2/README.md +++ b/gen/pagespeedonline2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-pagespeedonline2` library allows access to all features of the *Google pagespeedonline* service. -This documentation was generated from *pagespeedonline* crate version *0.1.6+20150317*, where *20150317* is the exact revision of the *pagespeedonline:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *pagespeedonline* crate version *0.1.7+20150317*, where *20150317* is the exact revision of the *pagespeedonline:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *pagespeedonline* *v2* API can be found at the [official documentation site](https://developers.google.com/speed/docs/insights/v2/getting-started). @@ -162,7 +162,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_pagespeedonline2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_pagespeedonline2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/pagespeedonline2/src/cmn.rs b/gen/pagespeedonline2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/pagespeedonline2/src/cmn.rs +++ b/gen/pagespeedonline2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/pagespeedonline2/src/lib.rs b/gen/pagespeedonline2/src/lib.rs index e019f666fd..55ac8cfb2d 100644 --- a/gen/pagespeedonline2/src/lib.rs +++ b/gen/pagespeedonline2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *pagespeedonline* crate version *0.1.6+20150317*, where *20150317* is the exact revision of the *pagespeedonline:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *pagespeedonline* crate version *0.1.7+20150317*, where *20150317* is the exact revision of the *pagespeedonline:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *pagespeedonline* *v2* API can be found at the //! [official documentation site](https://developers.google.com/speed/docs/insights/v2/getting-started). @@ -163,7 +163,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -172,7 +172,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -188,6 +187,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -287,7 +287,7 @@ impl<'a, C, A> Pagespeedonline<C, A> Pagespeedonline { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -296,7 +296,7 @@ impl<'a, C, A> Pagespeedonline<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -815,7 +815,7 @@ impl<'a, C, A> PagespeedapiRunpagespeedCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -823,7 +823,7 @@ impl<'a, C, A> PagespeedapiRunpagespeedCall<'a, C, A> where C: BorrowMut<hyper:: loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); diff --git a/gen/plus1-cli/Cargo.toml b/gen/plus1-cli/Cargo.toml index ad8728b810..9a4850abd5 100644 --- a/gen/plus1-cli/Cargo.toml +++ b/gen/plus1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-plus1-cli" -version = "0.1.0+20150303" +version = "0.2.0+20150303" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with plus (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/plus1-cli" @@ -17,15 +17,14 @@ keywords = ["plus", "google", "cli"] name = "plus1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-plus1] path = "../plus1" diff --git a/gen/plus1-cli/README.md b/gen/plus1-cli/README.md index 471e643ce0..c75e17e6f1 100644 --- a/gen/plus1-cli/README.md +++ b/gen/plus1-cli/README.md @@ -10,32 +10,37 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *plus* API can be found at the +[official documentation site](https://developers.google.com/+/api/). + # Usage -This documentation was generated from the *plus* API at revision *20150303*. The CLI is at version *0.1.0*. +This documentation was generated from the *plus* API at revision *20150303*. The CLI is at version *0.2.0*. ```bash - plus1 [options] activities get <activity-id> [-p <v>...] [-o <out>] - plus1 [options] activities list <user-id> <collection> [-p <v>...] [-o <out>] - plus1 [options] activities search <query> [-p <v>...] [-o <out>] - plus1 [options] comments get <comment-id> [-p <v>...] [-o <out>] - plus1 [options] comments list <activity-id> [-p <v>...] [-o <out>] - plus1 [options] moments insert <user-id> <collection> -r <kv>... [-p <v>...] [-o <out>] - plus1 [options] moments list <user-id> <collection> [-p <v>...] [-o <out>] - plus1 [options] moments remove <id> [-p <v>...] - plus1 [options] people get <user-id> [-p <v>...] [-o <out>] - plus1 [options] people list <user-id> <collection> [-p <v>...] [-o <out>] - plus1 [options] people list-by-activity <activity-id> <collection> [-p <v>...] [-o <out>] - plus1 [options] people search <query> [-p <v>...] [-o <out>] +plus1 [options] + activities + get <activity-id> [-p <v>]... [-o <out>] + list <user-id> <collection> [-p <v>]... [-o <out>] + search <query> [-p <v>]... [-o <out>] + comments + get <comment-id> [-p <v>]... [-o <out>] + list <activity-id> [-p <v>]... [-o <out>] + moments + insert <user-id> <collection> (-r <kv>)... [-p <v>]... [-o <out>] + list <user-id> <collection> [-p <v>]... [-o <out>] + remove <id> [-p <v>]... + people + get <user-id> [-p <v>]... [-o <out>] + list <user-id> <collection> [-p <v>]... [-o <out>] + list-by-activity <activity-id> <collection> [-p <v>]... [-o <out>] + search <query> [-p <v>]... [-o <out>] plus1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_plus1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/plus1-cli/mkdocs.yml b/gen/plus1-cli/mkdocs.yml index 6a4050153d..e0ad7baed1 100644 --- a/gen/plus1-cli/mkdocs.yml +++ b/gen/plus1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: plus v0.1.0+20150303 +site_name: plus v0.2.0+20150303 site_url: http://byron.github.io/google-apis-rs/google-plus1-cli site_description: Write integrating applications with bcore diff --git a/gen/plus1-cli/src/cmn.rs b/gen/plus1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/plus1-cli/src/cmn.rs +++ b/gen/plus1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/plus1-cli/src/main.rs b/gen/plus1-cli/src/main.rs index d3674b3fde..d24c024ca2 100644 --- a/gen/plus1-cli/src/main.rs +++ b/gen/plus1-cli/src/main.rs @@ -2,124 +2,103 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_plus1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - plus1 [options] activities get <activity-id> [-p <v>...] [-o <out>] - plus1 [options] activities list <user-id> <collection> [-p <v>...] [-o <out>] - plus1 [options] activities search <query> [-p <v>...] [-o <out>] - plus1 [options] comments get <comment-id> [-p <v>...] [-o <out>] - plus1 [options] comments list <activity-id> [-p <v>...] [-o <out>] - plus1 [options] moments insert <user-id> <collection> -r <kv>... [-p <v>...] [-o <out>] - plus1 [options] moments list <user-id> <collection> [-p <v>...] [-o <out>] - plus1 [options] moments remove <id> [-p <v>...] - plus1 [options] people get <user-id> [-p <v>...] [-o <out>] - plus1 [options] people list <user-id> <collection> [-p <v>...] [-o <out>] - plus1 [options] people list-by-activity <activity-id> <collection> [-p <v>...] [-o <out>] - plus1 [options] people search <query> [-p <v>...] [-o <out>] - plus1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_plus1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Plus<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _activities_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.activities().get(&self.opt.arg_activity_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _activities_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.activities().get(opt.value_of("activity-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _activities_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.activities().list(&self.opt.arg_user_id, &self.opt.arg_collection); - for parg in self.opt.arg_v.iter() { + fn _activities_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.activities().list(opt.value_of("user-id").unwrap_or(""), opt.value_of("collection").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -128,50 +107,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _activities_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.activities().search(&self.opt.arg_query); - for parg in self.opt.arg_v.iter() { + fn _activities_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.activities().search(opt.value_of("query").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -186,96 +169,104 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["order-by", "page-token", "language", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _comments_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.comments().get(&self.opt.arg_comment_id); - for parg in self.opt.arg_v.iter() { + fn _comments_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.comments().get(opt.value_of("comment-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _comments_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.comments().list(&self.opt.arg_activity_id); - for parg in self.opt.arg_v.iter() { + fn _comments_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.comments().list(opt.value_of("activity-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "sort-order" => { @@ -287,52 +278,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "sort-order", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _moments_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _moments_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Moment::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -869,61 +864,66 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["additional-name", "address-country", "address-locality", "address-region", "attendee-count", "best-rating", "birth-date", "caption", "content-size", "content-url", "date-created", "date-modified", "date-published", "description", "duration", "embed-url", "end-date", "family-name", "gender", "given-name", "height", "id", "image", "kind", "latitude", "longitude", "name", "object", "player-type", "post-office-box-number", "postal-code", "rating-value", "result", "start-date", "street-address", "target", "text", "thumbnail-url", "ticker-symbol", "type", "url", "width", "worst-rating"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.moments().insert(request, &self.opt.arg_user_id, &self.opt.arg_collection); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.moments().insert(request, opt.value_of("user-id").unwrap_or(""), opt.value_of("collection").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "debug" => { call = call.debug(arg_from_str(value.unwrap_or("false"), err, "debug", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["debug"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _moments_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.moments().list(&self.opt.arg_user_id, &self.opt.arg_collection); - for parg in self.opt.arg_v.iter() { + fn _moments_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.moments().list(opt.value_of("user-id").unwrap_or(""), opt.value_of("collection").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "type" => { @@ -938,140 +938,147 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "type", "max-results", "target-url"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _moments_remove(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.moments().remove(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _moments_remove(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.moments().remove(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _people_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.people().get(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _people_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.people().get(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _people_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.people().list(&self.opt.arg_user_id, &self.opt.arg_collection); - for parg in self.opt.arg_v.iter() { + fn _people_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.people().list(opt.value_of("user-id").unwrap_or(""), opt.value_of("collection").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1083,50 +1090,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["order-by", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _people_list_by_activity(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.people().list_by_activity(&self.opt.arg_activity_id, &self.opt.arg_collection); - for parg in self.opt.arg_v.iter() { + fn _people_list_by_activity(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.people().list_by_activity(opt.value_of("activity-id").unwrap_or(""), opt.value_of("collection").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1135,50 +1146,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _people_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.people().search(&self.opt.arg_query); - for parg in self.opt.arg_v.iter() { + fn _people_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.people().search(opt.value_of("query").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1190,110 +1205,143 @@ impl Engine { "language" => { call = call.language(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "language", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_activities { - if self.opt.cmd_get { - call_result = self._activities_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._activities_list(dry_run, &mut err); - } else if self.opt.cmd_search { - call_result = self._activities_search(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("activities", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._activities_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._activities_list(opt, dry_run, &mut err); + }, + ("search", Some(opt)) => { + call_result = self._activities_search(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("activities".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("comments", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._comments_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._comments_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("comments".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("moments", Some(opt)) => { + match opt.subcommand() { + ("insert", Some(opt)) => { + call_result = self._moments_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._moments_list(opt, dry_run, &mut err); + }, + ("remove", Some(opt)) => { + call_result = self._moments_remove(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("moments".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("people", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._people_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._people_list(opt, dry_run, &mut err); + }, + ("list-by-activity", Some(opt)) => { + call_result = self._people_list_by_activity(opt, dry_run, &mut err); + }, + ("search", Some(opt)) => { + call_result = self._people_search(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("people".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_comments { - if self.opt.cmd_get { - call_result = self._comments_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._comments_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_moments { - if self.opt.cmd_insert { - call_result = self._moments_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._moments_list(dry_run, &mut err); - } else if self.opt.cmd_remove { - call_result = self._moments_remove(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_people { - if self.opt.cmd_get { - call_result = self._people_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._people_list(dry_run, &mut err); - } else if self.opt.cmd_list_by_activity { - call_result = self._people_list_by_activity(dry_run, &mut err); - } else if self.opt.cmd_search { - call_result = self._people_search(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -1306,7 +1354,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1319,7 +1367,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1329,37 +1377,429 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Plus::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("activities", "methods: 'get', 'list' and 'search'", vec![ + ("get", + Some(r##"Get an activity."##), + "Details at http://byron.github.io/google-apis-rs/google_plus1_cli/activities_get", + vec![ + (Some(r##"activity-id"##), + None, + Some(r##"The ID of the activity to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all of the activities in the specified collection for a particular user."##), + "Details at http://byron.github.io/google-apis-rs/google_plus1_cli/activities_list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user to get activities for. The special value "me" can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"collection"##), + None, + Some(r##"The collection of activities to list."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("search", + Some(r##"Search public activities."##), + "Details at http://byron.github.io/google-apis-rs/google_plus1_cli/activities_search", + vec![ + (Some(r##"query"##), + None, + Some(r##"Full-text search query string."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("comments", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Get a comment."##), + "Details at http://byron.github.io/google-apis-rs/google_plus1_cli/comments_get", + vec![ + (Some(r##"comment-id"##), + None, + Some(r##"The ID of the comment to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all of the comments for an activity."##), + "Details at http://byron.github.io/google-apis-rs/google_plus1_cli/comments_list", + vec![ + (Some(r##"activity-id"##), + None, + Some(r##"The ID of the activity to get comments for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("moments", "methods: 'insert', 'list' and 'remove'", vec![ + ("insert", + Some(r##"Record a moment representing a user's action such as making a purchase or commenting on a blog."##), + "Details at http://byron.github.io/google-apis-rs/google_plus1_cli/moments_insert", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user to record actions for. The only valid values are "me" and the ID of the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"collection"##), + None, + Some(r##"The collection to which to write moments."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all of the moments for a particular user."##), + "Details at http://byron.github.io/google-apis-rs/google_plus1_cli/moments_list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user to get moments for. The special value "me" can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"collection"##), + None, + Some(r##"The collection of moments to list."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("remove", + Some(r##"Delete a moment."##), + "Details at http://byron.github.io/google-apis-rs/google_plus1_cli/moments_remove", + vec![ + (Some(r##"id"##), + None, + Some(r##"The ID of the moment to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("people", "methods: 'get', 'list', 'list-by-activity' and 'search'", vec![ + ("get", + Some(r##"Get a person's profile. If your app uses scope https://www.googleapis.com/auth/plus.login, this method is guaranteed to return ageRange and language."##), + "Details at http://byron.github.io/google-apis-rs/google_plus1_cli/people_get", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The ID of the person to get the profile for. The special value "me" can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all of the people in the specified collection."##), + "Details at http://byron.github.io/google-apis-rs/google_plus1_cli/people_list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"Get the collection of people for the person identified. Use "me" to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"collection"##), + None, + Some(r##"The collection of people to list."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-by-activity", + Some(r##"List all of the people in the specified collection for a particular activity."##), + "Details at http://byron.github.io/google-apis-rs/google_plus1_cli/people_list-by-activity", + vec![ + (Some(r##"activity-id"##), + None, + Some(r##"The ID of the activity to get the list of people for."##), + Some(true), + Some(false)), + + (Some(r##"collection"##), + None, + Some(r##"The collection of people to list."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("search", + Some(r##"Search all public profiles."##), + "Details at http://byron.github.io/google-apis-rs/google_plus1_cli/people_search", + vec![ + (Some(r##"query"##), + None, + Some(r##"Specify a query string for full text search of public text in all profiles."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("plus1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150303") + .about("The Google+ API enables developers to build on top of the Google+ platform.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_plus1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/plus1/Cargo.toml b/gen/plus1/Cargo.toml index 6195fb2729..4ffb25b1f9 100644 --- a/gen/plus1/Cargo.toml +++ b/gen/plus1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-plus1" -version = "0.1.6+20150303" +version = "0.1.7+20150303" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with plus (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/plus1" @@ -15,9 +15,10 @@ keywords = ["plus", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/plus1/README.md b/gen/plus1/README.md index 27131452db..8758c13d78 100644 --- a/gen/plus1/README.md +++ b/gen/plus1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-plus1` library allows access to all features of the *Google plus* service. -This documentation was generated from *plus* crate version *0.1.6+20150303*, where *20150303* is the exact revision of the *plus:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *plus* crate version *0.1.7+20150303*, where *20150303* is the exact revision of the *plus:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *plus* *v1* API can be found at the [official documentation site](https://developers.google.com/+/api/). @@ -168,7 +168,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_plus1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_plus1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/plus1/src/cmn.rs b/gen/plus1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/plus1/src/cmn.rs +++ b/gen/plus1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/plus1/src/lib.rs b/gen/plus1/src/lib.rs index 5992568c7c..34208aa5a6 100644 --- a/gen/plus1/src/lib.rs +++ b/gen/plus1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *plus* crate version *0.1.6+20150303*, where *20150303* is the exact revision of the *plus:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *plus* crate version *0.1.7+20150303*, where *20150303* is the exact revision of the *plus:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *plus* *v1* API can be found at the //! [official documentation site](https://developers.google.com/+/api/). @@ -169,7 +169,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -178,7 +178,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -194,6 +193,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -325,7 +325,7 @@ impl<'a, C, A> Plus<C, A> Plus { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -343,7 +343,7 @@ impl<'a, C, A> Plus<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -2089,6 +2089,7 @@ impl<'a, C, A> MomentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Moment)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2148,11 +2149,20 @@ impl<'a, C, A> MomentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2175,7 +2185,7 @@ impl<'a, C, A> MomentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2443,7 +2453,7 @@ impl<'a, C, A> MomentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2465,7 +2475,7 @@ impl<'a, C, A> MomentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2719,7 +2729,7 @@ impl<'a, C, A> MomentRemoveCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2741,7 +2751,7 @@ impl<'a, C, A> MomentRemoveCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2944,7 +2954,7 @@ impl<'a, C, A> ActivitySearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2966,7 +2976,7 @@ impl<'a, C, A> ActivitySearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3211,7 +3221,7 @@ impl<'a, C, A> ActivityGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3233,7 +3243,7 @@ impl<'a, C, A> ActivityGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3462,7 +3472,7 @@ impl<'a, C, A> ActivityListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3484,7 +3494,7 @@ impl<'a, C, A> ActivityListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3740,7 +3750,7 @@ impl<'a, C, A> CommentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3762,7 +3772,7 @@ impl<'a, C, A> CommentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4000,7 +4010,7 @@ impl<'a, C, A> CommentGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4022,7 +4032,7 @@ impl<'a, C, A> CommentGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4230,7 +4240,7 @@ impl<'a, C, A> PeopleSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4252,7 +4262,7 @@ impl<'a, C, A> PeopleSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4502,7 +4512,7 @@ impl<'a, C, A> PeopleListByActivityCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4524,7 +4534,7 @@ impl<'a, C, A> PeopleListByActivityCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4782,7 +4792,7 @@ impl<'a, C, A> PeopleListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4804,7 +4814,7 @@ impl<'a, C, A> PeopleListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5052,7 +5062,7 @@ impl<'a, C, A> PeopleGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5074,7 +5084,7 @@ impl<'a, C, A> PeopleGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/plusdomains1-cli/Cargo.toml b/gen/plusdomains1-cli/Cargo.toml index ed08c527e8..174c9f5c47 100644 --- a/gen/plusdomains1-cli/Cargo.toml +++ b/gen/plusdomains1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-plusdomains1-cli" -version = "0.1.0+20150303" +version = "0.2.0+20150303" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with plusDomains (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/plusdomains1-cli" @@ -17,15 +17,14 @@ keywords = ["plusDomains", "google", "cli"] name = "plusdomains1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-plusdomains1] path = "../plusdomains1" diff --git a/gen/plusdomains1-cli/README.md b/gen/plusdomains1-cli/README.md index e5ba604b99..bc7df77176 100644 --- a/gen/plusdomains1-cli/README.md +++ b/gen/plusdomains1-cli/README.md @@ -10,40 +10,47 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *plusDomains* API can be found at the +[official documentation site](https://developers.google.com/+/domains/). + # Usage -This documentation was generated from the *plusDomains* API at revision *20150303*. The CLI is at version *0.1.0*. +This documentation was generated from the *plusDomains* API at revision *20150303*. The CLI is at version *0.2.0*. ```bash - plusdomains1 [options] activities get <activity-id> [-p <v>...] [-o <out>] - plusdomains1 [options] activities insert <user-id> -r <kv>... [-p <v>...] [-o <out>] - plusdomains1 [options] activities list <user-id> <collection> [-p <v>...] [-o <out>] - plusdomains1 [options] audiences list <user-id> [-p <v>...] [-o <out>] - plusdomains1 [options] circles add-people <circle-id> [-p <v>...] [-o <out>] - plusdomains1 [options] circles get <circle-id> [-p <v>...] [-o <out>] - plusdomains1 [options] circles insert <user-id> -r <kv>... [-p <v>...] [-o <out>] - plusdomains1 [options] circles list <user-id> [-p <v>...] [-o <out>] - plusdomains1 [options] circles patch <circle-id> -r <kv>... [-p <v>...] [-o <out>] - plusdomains1 [options] circles remove <circle-id> [-p <v>...] - plusdomains1 [options] circles remove-people <circle-id> [-p <v>...] - plusdomains1 [options] circles update <circle-id> -r <kv>... [-p <v>...] [-o <out>] - plusdomains1 [options] comments get <comment-id> [-p <v>...] [-o <out>] - plusdomains1 [options] comments insert <activity-id> -r <kv>... [-p <v>...] [-o <out>] - plusdomains1 [options] comments list <activity-id> [-p <v>...] [-o <out>] - plusdomains1 [options] media insert <user-id> <collection> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - plusdomains1 [options] people get <user-id> [-p <v>...] [-o <out>] - plusdomains1 [options] people list <user-id> <collection> [-p <v>...] [-o <out>] - plusdomains1 [options] people list-by-activity <activity-id> <collection> [-p <v>...] [-o <out>] - plusdomains1 [options] people list-by-circle <circle-id> [-p <v>...] [-o <out>] +plusdomains1 [options] + activities + get <activity-id> [-p <v>]... [-o <out>] + insert <user-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <user-id> <collection> [-p <v>]... [-o <out>] + audiences + list <user-id> [-p <v>]... [-o <out>] + circles + add-people <circle-id> [-p <v>]... [-o <out>] + get <circle-id> [-p <v>]... [-o <out>] + insert <user-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <user-id> [-p <v>]... [-o <out>] + patch <circle-id> (-r <kv>)... [-p <v>]... [-o <out>] + remove <circle-id> [-p <v>]... + remove-people <circle-id> [-p <v>]... + update <circle-id> (-r <kv>)... [-p <v>]... [-o <out>] + comments + get <comment-id> [-p <v>]... [-o <out>] + insert <activity-id> (-r <kv>)... [-p <v>]... [-o <out>] + list <activity-id> [-p <v>]... [-o <out>] + media + insert <user-id> <collection> (-r <kv>)... (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + people + get <user-id> [-p <v>]... [-o <out>] + list <user-id> <collection> [-p <v>]... [-o <out>] + list-by-activity <activity-id> <collection> [-p <v>]... [-o <out>] + list-by-circle <circle-id> [-p <v>]... [-o <out>] plusdomains1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_plusdomains1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/plusdomains1-cli/mkdocs.yml b/gen/plusdomains1-cli/mkdocs.yml index 3e8b71e3f1..a69c47a526 100644 --- a/gen/plusdomains1-cli/mkdocs.yml +++ b/gen/plusdomains1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: plusDomains v0.1.0+20150303 +site_name: plusDomains v0.2.0+20150303 site_url: http://byron.github.io/google-apis-rs/google-plusdomains1-cli site_description: Write integrating applications with bcore diff --git a/gen/plusdomains1-cli/src/cmn.rs b/gen/plusdomains1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/plusdomains1-cli/src/cmn.rs +++ b/gen/plusdomains1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/plusdomains1-cli/src/main.rs b/gen/plusdomains1-cli/src/main.rs index 52a5c8c538..91da68b1d1 100644 --- a/gen/plusdomains1-cli/src/main.rs +++ b/gen/plusdomains1-cli/src/main.rs @@ -2,134 +2,105 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_plusdomains1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - plusdomains1 [options] activities get <activity-id> [-p <v>...] [-o <out>] - plusdomains1 [options] activities insert <user-id> -r <kv>... [-p <v>...] [-o <out>] - plusdomains1 [options] activities list <user-id> <collection> [-p <v>...] [-o <out>] - plusdomains1 [options] audiences list <user-id> [-p <v>...] [-o <out>] - plusdomains1 [options] circles add-people <circle-id> [-p <v>...] [-o <out>] - plusdomains1 [options] circles get <circle-id> [-p <v>...] [-o <out>] - plusdomains1 [options] circles insert <user-id> -r <kv>... [-p <v>...] [-o <out>] - plusdomains1 [options] circles list <user-id> [-p <v>...] [-o <out>] - plusdomains1 [options] circles patch <circle-id> -r <kv>... [-p <v>...] [-o <out>] - plusdomains1 [options] circles remove <circle-id> [-p <v>...] - plusdomains1 [options] circles remove-people <circle-id> [-p <v>...] - plusdomains1 [options] circles update <circle-id> -r <kv>... [-p <v>...] [-o <out>] - plusdomains1 [options] comments get <comment-id> [-p <v>...] [-o <out>] - plusdomains1 [options] comments insert <activity-id> -r <kv>... [-p <v>...] [-o <out>] - plusdomains1 [options] comments list <activity-id> [-p <v>...] [-o <out>] - plusdomains1 [options] media insert <user-id> <collection> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - plusdomains1 [options] people get <user-id> [-p <v>...] [-o <out>] - plusdomains1 [options] people list <user-id> <collection> [-p <v>...] [-o <out>] - plusdomains1 [options] people list-by-activity <activity-id> <collection> [-p <v>...] [-o <out>] - plusdomains1 [options] people list-by-circle <circle-id> [-p <v>...] [-o <out>] - plusdomains1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_plusdomains1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::PlusDomains<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _activities_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.activities().get(&self.opt.arg_activity_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _activities_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.activities().get(opt.value_of("activity-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _activities_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _activities_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Activity::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -447,61 +418,66 @@ impl Engine { request.published = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["access", "actor", "address", "annotation", "can-comment", "can-plusone", "can-update", "content", "crosspost-source", "description", "display-name", "domain-restricted", "etag", "family-name", "formatted", "geocode", "given-name", "id", "image", "is-plus-oned", "kind", "latitude", "location", "longitude", "name", "object", "object-type", "original-content", "place-id", "place-name", "plusoners", "position", "provider", "published", "radius", "replies", "resharers", "resharing-disabled", "self-link", "status-for-viewer", "title", "total-items", "updated", "url", "verb"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.activities().insert(request, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.activities().insert(request, opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "preview" => { call = call.preview(arg_from_str(value.unwrap_or("false"), err, "preview", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["preview"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _activities_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.activities().list(&self.opt.arg_user_id, &self.opt.arg_collection); - for parg in self.opt.arg_v.iter() { + fn _activities_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.activities().list(opt.value_of("user-id").unwrap_or(""), opt.value_of("collection").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -510,50 +486,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _audiences_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.audiences().list(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _audiences_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.audiences().list(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -562,50 +542,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _circles_add_people(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.circles().add_people(&self.opt.arg_circle_id); - for parg in self.opt.arg_v.iter() { + fn _circles_add_people(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.circles().add_people(opt.value_of("circle-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "user-id" => { @@ -614,98 +598,106 @@ impl Engine { "email" => { call = call.add_email(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["user-id", "email"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _circles_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.circles().get(&self.opt.arg_circle_id); - for parg in self.opt.arg_v.iter() { + fn _circles_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.circles().get(opt.value_of("circle-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _circles_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _circles_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Circle::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -752,58 +744,63 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["description", "display-name", "etag", "id", "kind", "people", "self-link", "total-items"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.circles().insert(request, &self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.circles().insert(request, opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _circles_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.circles().list(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _circles_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.circles().list(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -812,52 +809,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _circles_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _circles_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Circle::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -904,102 +905,106 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["description", "display-name", "etag", "id", "kind", "people", "self-link", "total-items"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.circles().patch(request, &self.opt.arg_circle_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.circles().patch(request, opt.value_of("circle-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _circles_remove(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.circles().remove(&self.opt.arg_circle_id); - for parg in self.opt.arg_v.iter() { + fn _circles_remove(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.circles().remove(opt.value_of("circle-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _circles_remove_people(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.circles().remove_people(&self.opt.arg_circle_id); - for parg in self.opt.arg_v.iter() { + fn _circles_remove_people(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.circles().remove_people(opt.value_of("circle-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "user-id" => { @@ -1008,50 +1013,49 @@ impl Engine { "email" => { call = call.add_email(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["user-id", "email"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _circles_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _circles_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Circle::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1098,106 +1102,115 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["description", "display-name", "etag", "id", "kind", "people", "self-link", "total-items"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.circles().update(request, &self.opt.arg_circle_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.circles().update(request, opt.value_of("circle-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _comments_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.comments().get(&self.opt.arg_comment_id); - for parg in self.opt.arg_v.iter() { + fn _comments_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.comments().get(opt.value_of("comment-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _comments_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _comments_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Comment::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1297,58 +1310,63 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["actor", "content", "display-name", "etag", "id", "image", "kind", "object", "object-type", "original-content", "plusoners", "published", "self-link", "total-items", "updated", "url", "verb"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.comments().insert(request, &self.opt.arg_activity_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.comments().insert(request, opt.value_of("activity-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _comments_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.comments().list(&self.opt.arg_activity_id); - for parg in self.opt.arg_v.iter() { + fn _comments_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.comments().list(opt.value_of("activity-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "sort-order" => { @@ -1360,52 +1378,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "sort-order", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _media_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _media_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Media::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1518,114 +1540,117 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author", "display-name", "etag", "exif", "height", "id", "image", "kind", "media-created-time", "media-url", "published", "size-bytes", "summary", "time", "updated", "url", "video-duration", "video-status", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.media().insert(request, &self.opt.arg_user_id, &self.opt.arg_collection); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.media().insert(request, opt.value_of("user-id").unwrap_or(""), opt.value_of("collection").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); + if dry_run { + Ok(()) + } else { + assert!(err.issues.len() == 0); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); + } + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); - if dry_run { - None - } else { - assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); - } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _people_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.people().get(&self.opt.arg_user_id); - for parg in self.opt.arg_v.iter() { + fn _people_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.people().get(opt.value_of("user-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _people_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.people().list(&self.opt.arg_user_id, &self.opt.arg_collection); - for parg in self.opt.arg_v.iter() { + fn _people_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.people().list(opt.value_of("user-id").unwrap_or(""), opt.value_of("collection").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1637,50 +1662,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["order-by", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _people_list_by_activity(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.people().list_by_activity(&self.opt.arg_activity_id, &self.opt.arg_collection); - for parg in self.opt.arg_v.iter() { + fn _people_list_by_activity(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.people().list_by_activity(opt.value_of("activity-id").unwrap_or(""), opt.value_of("collection").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1689,50 +1718,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _people_list_by_circle(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.people().list_by_circle(&self.opt.arg_circle_id); - for parg in self.opt.arg_v.iter() { + fn _people_list_by_circle(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.people().list_by_circle(opt.value_of("circle-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1741,136 +1774,183 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_activities { - if self.opt.cmd_get { - call_result = self._activities_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._activities_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._activities_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("activities", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._activities_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._activities_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._activities_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("activities".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("audiences", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._audiences_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("audiences".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("circles", Some(opt)) => { + match opt.subcommand() { + ("add-people", Some(opt)) => { + call_result = self._circles_add_people(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._circles_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._circles_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._circles_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._circles_patch(opt, dry_run, &mut err); + }, + ("remove", Some(opt)) => { + call_result = self._circles_remove(opt, dry_run, &mut err); + }, + ("remove-people", Some(opt)) => { + call_result = self._circles_remove_people(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._circles_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("circles".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("comments", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._comments_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._comments_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._comments_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("comments".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("media", Some(opt)) => { + match opt.subcommand() { + ("insert", Some(opt)) => { + call_result = self._media_insert(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("media".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("people", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._people_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._people_list(opt, dry_run, &mut err); + }, + ("list-by-activity", Some(opt)) => { + call_result = self._people_list_by_activity(opt, dry_run, &mut err); + }, + ("list-by-circle", Some(opt)) => { + call_result = self._people_list_by_circle(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("people".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_audiences { - if self.opt.cmd_list { - call_result = self._audiences_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_circles { - if self.opt.cmd_add_people { - call_result = self._circles_add_people(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._circles_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._circles_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._circles_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._circles_patch(dry_run, &mut err); - } else if self.opt.cmd_remove { - call_result = self._circles_remove(dry_run, &mut err); - } else if self.opt.cmd_remove_people { - call_result = self._circles_remove_people(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._circles_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_comments { - if self.opt.cmd_get { - call_result = self._comments_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._comments_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._comments_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_media { - if self.opt.cmd_insert { - call_result = self._media_insert(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_people { - if self.opt.cmd_get { - call_result = self._people_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._people_list(dry_run, &mut err); - } else if self.opt.cmd_list_by_activity { - call_result = self._people_list_by_activity(dry_run, &mut err); - } else if self.opt.cmd_list_by_circle { - call_result = self._people_list_by_circle(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -1883,7 +1963,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1896,7 +1976,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1906,37 +1986,647 @@ impl Engine { let engine = Engine { opt: opt, hub: api::PlusDomains::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let upload_value_names = ["mode", "file"]; + let arg_data = [ + ("activities", "methods: 'get', 'insert' and 'list'", vec![ + ("get", + Some(r##"Get an activity."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/activities_get", + vec![ + (Some(r##"activity-id"##), + None, + Some(r##"The ID of the activity to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Create a new activity for the authenticated user."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/activities_insert", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user to create the activity on behalf of. Its value should be "me", to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all of the activities in the specified collection for a particular user."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/activities_list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user to get activities for. The special value "me" can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"collection"##), + None, + Some(r##"The collection of activities to list."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("audiences", "methods: 'list'", vec![ + ("list", + Some(r##"List all of the audiences to which a user can share."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/audiences_list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user to get audiences for. The special value "me" can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("circles", "methods: 'add-people', 'get', 'insert', 'list', 'patch', 'remove', 'remove-people' and 'update'", vec![ + ("add-people", + Some(r##"Add a person to a circle. Google+ limits certain circle operations, including the number of circle adds. Learn More."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/circles_add-people", + vec![ + (Some(r##"circle-id"##), + None, + Some(r##"The ID of the circle to add the person to."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Get a circle."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/circles_get", + vec![ + (Some(r##"circle-id"##), + None, + Some(r##"The ID of the circle to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Create a new circle for the authenticated user."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/circles_insert", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user to create the circle on behalf of. The value "me" can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all of the circles for a user."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/circles_list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user to get circles for. The special value "me" can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update a circle's description. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/circles_patch", + vec![ + (Some(r##"circle-id"##), + None, + Some(r##"The ID of the circle to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("remove", + Some(r##"Delete a circle."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/circles_remove", + vec![ + (Some(r##"circle-id"##), + None, + Some(r##"The ID of the circle to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("remove-people", + Some(r##"Remove a person from a circle."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/circles_remove-people", + vec![ + (Some(r##"circle-id"##), + None, + Some(r##"The ID of the circle to remove the person from."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("update", + Some(r##"Update a circle's description."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/circles_update", + vec![ + (Some(r##"circle-id"##), + None, + Some(r##"The ID of the circle to update."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("comments", "methods: 'get', 'insert' and 'list'", vec![ + ("get", + Some(r##"Get a comment."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/comments_get", + vec![ + (Some(r##"comment-id"##), + None, + Some(r##"The ID of the comment to get."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Create a new comment in reply to an activity."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/comments_insert", + vec![ + (Some(r##"activity-id"##), + None, + Some(r##"The ID of the activity to reply to."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all of the comments for an activity."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/comments_list", + vec![ + (Some(r##"activity-id"##), + None, + Some(r##"The ID of the activity to get comments for."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("media", "methods: 'insert'", vec![ + ("insert", + Some(r##"Add a new media item to an album. The current upload size limitations are 36MB for a photo and 1GB for a video. Uploads do not count against quota if photos are less than 2048 pixels on their longest side or videos are less than 15 minutes in length."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/media_insert", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The ID of the user to create the activity on behalf of."##), + Some(true), + Some(false)), + + (Some(r##"collection"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("people", "methods: 'get', 'list', 'list-by-activity' and 'list-by-circle'", vec![ + ("get", + Some(r##"Get a person's profile."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/people_get", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"The ID of the person to get the profile for. The special value "me" can be used to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List all of the people in the specified collection."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/people_list", + vec![ + (Some(r##"user-id"##), + None, + Some(r##"Get the collection of people for the person identified. Use "me" to indicate the authenticated user."##), + Some(true), + Some(false)), + + (Some(r##"collection"##), + None, + Some(r##"The collection of people to list."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-by-activity", + Some(r##"List all of the people in the specified collection for a particular activity."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/people_list-by-activity", + vec![ + (Some(r##"activity-id"##), + None, + Some(r##"The ID of the activity to get the list of people for."##), + Some(true), + Some(false)), + + (Some(r##"collection"##), + None, + Some(r##"The collection of people to list."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-by-circle", + Some(r##"List all of the people who are members of a circle."##), + "Details at http://byron.github.io/google-apis-rs/google_plusdomains1_cli/people_list-by-circle", + vec![ + (Some(r##"circle-id"##), + None, + Some(r##"The ID of the circle to get the members of."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("plusdomains1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150303") + .about("The Google+ API enables developers to build on top of the Google+ platform.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_plusdomains1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + if arg_name_str == "mode" { + arg = arg.number_of_values(2); + arg = arg.value_names(&upload_value_names); + + scmd = scmd.arg(Arg::with_name("mime") + .short("m") + .requires("mode") + .required(false) + .help("The file's mime time, like 'application/octet-stream'") + .takes_value(true)); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/plusdomains1/Cargo.toml b/gen/plusdomains1/Cargo.toml index d792de681a..79a76e252f 100644 --- a/gen/plusdomains1/Cargo.toml +++ b/gen/plusdomains1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-plusdomains1" -version = "0.1.6+20150303" +version = "0.1.7+20150303" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with plusDomains (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/plusdomains1" @@ -15,9 +15,10 @@ keywords = ["plusDomains", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/plusdomains1/README.md b/gen/plusdomains1/README.md index 03d847dbf9..6179a6b501 100644 --- a/gen/plusdomains1/README.md +++ b/gen/plusdomains1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-plusdomains1` library allows access to all features of the *Google plusDomains* service. -This documentation was generated from *plusDomains* crate version *0.1.6+20150303*, where *20150303* is the exact revision of the *plusDomains:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *plusDomains* crate version *0.1.7+20150303*, where *20150303* is the exact revision of the *plusDomains:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *plusDomains* *v1* API can be found at the [official documentation site](https://developers.google.com/+/domains/). @@ -180,7 +180,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_plusdomains1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_plusdomains1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/plusdomains1/src/cmn.rs b/gen/plusdomains1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/plusdomains1/src/cmn.rs +++ b/gen/plusdomains1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/plusdomains1/src/lib.rs b/gen/plusdomains1/src/lib.rs index 6e04be32a6..43a39e8d15 100644 --- a/gen/plusdomains1/src/lib.rs +++ b/gen/plusdomains1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *plusDomains* crate version *0.1.6+20150303*, where *20150303* is the exact revision of the *plusDomains:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *plusDomains* crate version *0.1.7+20150303*, where *20150303* is the exact revision of the *plusDomains:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *plusDomains* *v1* API can be found at the //! [official documentation site](https://developers.google.com/+/domains/). @@ -181,7 +181,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -190,7 +190,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -206,6 +205,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -360,7 +360,7 @@ impl<'a, C, A> PlusDomains<C, A> PlusDomains { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -384,7 +384,7 @@ impl<'a, C, A> PlusDomains<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -2506,7 +2506,7 @@ impl<'a, C, A> CircleRemovePeopleCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2528,7 +2528,7 @@ impl<'a, C, A> CircleRemovePeopleCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2703,6 +2703,7 @@ impl<'a, C, A> CircleInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Circle)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2758,11 +2759,20 @@ impl<'a, C, A> CircleInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2785,7 +2795,7 @@ impl<'a, C, A> CircleInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3032,7 +3042,7 @@ impl<'a, C, A> CircleAddPeopleCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3054,7 +3064,7 @@ impl<'a, C, A> CircleAddPeopleCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3287,7 +3297,7 @@ impl<'a, C, A> CircleGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3309,7 +3319,7 @@ impl<'a, C, A> CircleGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3536,7 +3546,7 @@ impl<'a, C, A> CircleListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3558,7 +3568,7 @@ impl<'a, C, A> CircleListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3741,6 +3751,7 @@ impl<'a, C, A> CircleUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Circle)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3796,11 +3807,20 @@ impl<'a, C, A> CircleUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3823,7 +3843,7 @@ impl<'a, C, A> CircleUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4004,6 +4024,7 @@ impl<'a, C, A> CirclePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Circle)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4059,11 +4080,20 @@ impl<'a, C, A> CirclePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4086,7 +4116,7 @@ impl<'a, C, A> CirclePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4314,7 +4344,7 @@ impl<'a, C, A> CircleRemoveCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4336,7 +4366,7 @@ impl<'a, C, A> CircleRemoveCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4497,6 +4527,7 @@ impl<'a, C, A> ActivityInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Activity)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4555,11 +4586,20 @@ impl<'a, C, A> ActivityInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4582,7 +4622,7 @@ impl<'a, C, A> ActivityInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4818,7 +4858,7 @@ impl<'a, C, A> ActivityGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4840,7 +4880,7 @@ impl<'a, C, A> ActivityGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5069,7 +5109,7 @@ impl<'a, C, A> ActivityListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5091,7 +5131,7 @@ impl<'a, C, A> ActivityListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5342,7 +5382,7 @@ impl<'a, C, A> PeopleListByCircleCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5364,7 +5404,7 @@ impl<'a, C, A> PeopleListByCircleCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5612,7 +5652,7 @@ impl<'a, C, A> PeopleListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5634,7 +5674,7 @@ impl<'a, C, A> PeopleListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5882,7 +5922,7 @@ impl<'a, C, A> PeopleGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5904,7 +5944,7 @@ impl<'a, C, A> PeopleGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6133,7 +6173,7 @@ impl<'a, C, A> PeopleListByActivityCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6155,7 +6195,7 @@ impl<'a, C, A> PeopleListByActivityCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6351,6 +6391,7 @@ impl<'a, C, A> MediaInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, Media)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6415,11 +6456,20 @@ impl<'a, C, A> MediaInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6472,7 +6522,7 @@ impl<'a, C, A> MediaInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o _ => (&mut request_value_reader as &mut io::Read, ContentType(json_mime_type.clone())), }; let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(content_type) @@ -6520,7 +6570,7 @@ impl<'a, C, A> MediaInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -6548,6 +6598,7 @@ impl<'a, C, A> MediaInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -6734,6 +6785,7 @@ impl<'a, C, A> CommentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Comment)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6789,11 +6841,20 @@ impl<'a, C, A> CommentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6816,7 +6877,7 @@ impl<'a, C, A> CommentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7060,7 +7121,7 @@ impl<'a, C, A> CommentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7082,7 +7143,7 @@ impl<'a, C, A> CommentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7320,7 +7381,7 @@ impl<'a, C, A> CommentGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7342,7 +7403,7 @@ impl<'a, C, A> CommentGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7569,7 +7630,7 @@ impl<'a, C, A> AudienceListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7591,7 +7652,7 @@ impl<'a, C, A> AudienceListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/prediction1d6-cli/Cargo.toml b/gen/prediction1d6-cli/Cargo.toml index 00b813c6a6..8d6991c145 100644 --- a/gen/prediction1d6-cli/Cargo.toml +++ b/gen/prediction1d6-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-prediction1d6-cli" -version = "0.1.0+20140522" +version = "0.2.0+20140522" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with prediction (protocol v1.6)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/prediction1d6-cli" @@ -17,15 +17,14 @@ keywords = ["prediction", "google", "cli"] name = "prediction1d6" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-prediction1d6] path = "../prediction1d6" diff --git a/gen/prediction1d6-cli/README.md b/gen/prediction1d6-cli/README.md index fcff4605bc..8de6f3cb4b 100644 --- a/gen/prediction1d6-cli/README.md +++ b/gen/prediction1d6-cli/README.md @@ -10,28 +10,31 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *prediction* API can be found at the +[official documentation site](https://developers.google.com/prediction/docs/developer-guide). + # Usage -This documentation was generated from the *prediction* API at revision *20140522*. The CLI is at version *0.1.0*. +This documentation was generated from the *prediction* API at revision *20140522*. The CLI is at version *0.2.0*. ```bash - prediction1d6 [options] hostedmodels predict <project> <hosted-model-name> -r <kv>... [-p <v>...] [-o <out>] - prediction1d6 [options] trainedmodels analyze <project> <id> [-p <v>...] [-o <out>] - prediction1d6 [options] trainedmodels delete <project> <id> [-p <v>...] - prediction1d6 [options] trainedmodels get <project> <id> [-p <v>...] [-o <out>] - prediction1d6 [options] trainedmodels insert <project> -r <kv>... [-p <v>...] [-o <out>] - prediction1d6 [options] trainedmodels list <project> [-p <v>...] [-o <out>] - prediction1d6 [options] trainedmodels predict <project> <id> -r <kv>... [-p <v>...] [-o <out>] - prediction1d6 [options] trainedmodels update <project> <id> -r <kv>... [-p <v>...] [-o <out>] +prediction1d6 [options] + hostedmodels + predict <project> <hosted-model-name> (-r <kv>)... [-p <v>]... [-o <out>] + trainedmodels + analyze <project> <id> [-p <v>]... [-o <out>] + delete <project> <id> [-p <v>]... + get <project> <id> [-p <v>]... [-o <out>] + insert <project> (-r <kv>)... [-p <v>]... [-o <out>] + list <project> [-p <v>]... [-o <out>] + predict <project> <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <project> <id> (-r <kv>)... [-p <v>]... [-o <out>] prediction1d6 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_prediction1d6_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/prediction1d6-cli/mkdocs.yml b/gen/prediction1d6-cli/mkdocs.yml index 6d33de3c7f..3fc662c266 100644 --- a/gen/prediction1d6-cli/mkdocs.yml +++ b/gen/prediction1d6-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: prediction v0.1.0+20140522 +site_name: prediction v0.2.0+20140522 site_url: http://byron.github.io/google-apis-rs/google-prediction1d6-cli site_description: Write integrating applications with bcore diff --git a/gen/prediction1d6-cli/src/cmn.rs b/gen/prediction1d6-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/prediction1d6-cli/src/cmn.rs +++ b/gen/prediction1d6-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/prediction1d6-cli/src/main.rs b/gen/prediction1d6-cli/src/main.rs index bc01507695..53534f66c1 100644 --- a/gen/prediction1d6-cli/src/main.rs +++ b/gen/prediction1d6-cli/src/main.rs @@ -2,76 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_prediction1d6 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - prediction1d6 [options] hostedmodels predict <project> <hosted-model-name> -r <kv>... [-p <v>...] [-o <out>] - prediction1d6 [options] trainedmodels analyze <project> <id> [-p <v>...] [-o <out>] - prediction1d6 [options] trainedmodels delete <project> <id> [-p <v>...] - prediction1d6 [options] trainedmodels get <project> <id> [-p <v>...] [-o <out>] - prediction1d6 [options] trainedmodels insert <project> -r <kv>... [-p <v>...] [-o <out>] - prediction1d6 [options] trainedmodels list <project> [-p <v>...] [-o <out>] - prediction1d6 [options] trainedmodels predict <project> <id> -r <kv>... [-p <v>...] [-o <out>] - prediction1d6 [options] trainedmodels update <project> <id> -r <kv>... [-p <v>...] [-o <out>] - prediction1d6 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_prediction1d6_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Prediction<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _hostedmodels_predict(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _hostedmodels_predict(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Input::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -87,196 +66,208 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.hostedmodels().predict(request, &self.opt.arg_project, &self.opt.arg_hosted_model_name); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.hostedmodels().predict(request, opt.value_of("project").unwrap_or(""), opt.value_of("hosted-model-name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _trainedmodels_analyze(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.trainedmodels().analyze(&self.opt.arg_project, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _trainedmodels_analyze(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.trainedmodels().analyze(opt.value_of("project").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _trainedmodels_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.trainedmodels().delete(&self.opt.arg_project, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _trainedmodels_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.trainedmodels().delete(opt.value_of("project").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _trainedmodels_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.trainedmodels().get(&self.opt.arg_project, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _trainedmodels_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.trainedmodels().get(opt.value_of("project").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _trainedmodels_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _trainedmodels_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Insert::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -310,58 +301,63 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "model-type", "source-model", "storage-data-location", "storage-pmml-location", "storage-pmml-model-location"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.trainedmodels().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.trainedmodels().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _trainedmodels_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.trainedmodels().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _trainedmodels_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.trainedmodels().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -370,52 +366,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _trainedmodels_predict(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _trainedmodels_predict(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Input::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -431,60 +431,65 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.trainedmodels().predict(request, &self.opt.arg_project, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.trainedmodels().predict(request, opt.value_of("project").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _trainedmodels_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _trainedmodels_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Update::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -503,100 +508,124 @@ impl Engine { request.output = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["output"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.trainedmodels().update(request, &self.opt.arg_project, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.trainedmodels().update(request, opt.value_of("project").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_hostedmodels { - if self.opt.cmd_predict { - call_result = self._hostedmodels_predict(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("hostedmodels", Some(opt)) => { + match opt.subcommand() { + ("predict", Some(opt)) => { + call_result = self._hostedmodels_predict(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("hostedmodels".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("trainedmodels", Some(opt)) => { + match opt.subcommand() { + ("analyze", Some(opt)) => { + call_result = self._trainedmodels_analyze(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._trainedmodels_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._trainedmodels_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._trainedmodels_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._trainedmodels_list(opt, dry_run, &mut err); + }, + ("predict", Some(opt)) => { + call_result = self._trainedmodels_predict(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._trainedmodels_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("trainedmodels".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_trainedmodels { - if self.opt.cmd_analyze { - call_result = self._trainedmodels_analyze(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._trainedmodels_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._trainedmodels_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._trainedmodels_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._trainedmodels_list(dry_run, &mut err); - } else if self.opt.cmd_predict { - call_result = self._trainedmodels_predict(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._trainedmodels_update(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -609,7 +638,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -622,7 +651,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -632,37 +661,359 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Prediction::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("hostedmodels", "methods: 'predict'", vec![ + ("predict", + Some(r##"Submit input and request an output against a hosted model."##), + "Details at http://byron.github.io/google-apis-rs/google_prediction1d6_cli/hostedmodels_predict", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project associated with the model."##), + Some(true), + Some(false)), + + (Some(r##"hosted-model-name"##), + None, + Some(r##"The name of a hosted model."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("trainedmodels", "methods: 'analyze', 'delete', 'get', 'insert', 'list', 'predict' and 'update'", vec![ + ("analyze", + Some(r##"Get analysis of the model and the data the model was trained on."##), + "Details at http://byron.github.io/google-apis-rs/google_prediction1d6_cli/trainedmodels_analyze", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project associated with the model."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The unique name for the predictive model."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Delete a trained model."##), + "Details at http://byron.github.io/google-apis-rs/google_prediction1d6_cli/trainedmodels_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project associated with the model."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The unique name for the predictive model."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Check training status of your model."##), + "Details at http://byron.github.io/google-apis-rs/google_prediction1d6_cli/trainedmodels_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project associated with the model."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The unique name for the predictive model."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Train a Prediction API model."##), + "Details at http://byron.github.io/google-apis-rs/google_prediction1d6_cli/trainedmodels_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project associated with the model."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List available models."##), + "Details at http://byron.github.io/google-apis-rs/google_prediction1d6_cli/trainedmodels_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project associated with the model."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("predict", + Some(r##"Submit model id and request a prediction."##), + "Details at http://byron.github.io/google-apis-rs/google_prediction1d6_cli/trainedmodels_predict", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project associated with the model."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The unique name for the predictive model."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Add new data to a trained model."##), + "Details at http://byron.github.io/google-apis-rs/google_prediction1d6_cli/trainedmodels_update", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project associated with the model."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The unique name for the predictive model."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("prediction1d6") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20140522") + .about("Lets you access a cloud hosted machine learning service that makes it easy to build smart apps") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_prediction1d6_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/prediction1d6/Cargo.toml b/gen/prediction1d6/Cargo.toml index a85f237d63..af7ba20606 100644 --- a/gen/prediction1d6/Cargo.toml +++ b/gen/prediction1d6/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-prediction1d6" -version = "0.1.6+20140522" +version = "0.1.7+20140522" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with prediction (protocol v1.6)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/prediction1d6" @@ -15,9 +15,10 @@ keywords = ["prediction", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/prediction1d6/README.md b/gen/prediction1d6/README.md index d06060ef0f..d75044b30f 100644 --- a/gen/prediction1d6/README.md +++ b/gen/prediction1d6/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-prediction1d6` library allows access to all features of the *Google prediction* service. -This documentation was generated from *prediction* crate version *0.1.6+20140522*, where *20140522* is the exact revision of the *prediction:v1.6* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *prediction* crate version *0.1.7+20140522*, where *20140522* is the exact revision of the *prediction:v1.6* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *prediction* *v1d6* API can be found at the [official documentation site](https://developers.google.com/prediction/docs/developer-guide). @@ -167,7 +167,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_prediction1d6/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_prediction1d6/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/prediction1d6/src/cmn.rs b/gen/prediction1d6/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/prediction1d6/src/cmn.rs +++ b/gen/prediction1d6/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/prediction1d6/src/lib.rs b/gen/prediction1d6/src/lib.rs index 131fe41ed6..fe1e1ab7ef 100644 --- a/gen/prediction1d6/src/lib.rs +++ b/gen/prediction1d6/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *prediction* crate version *0.1.6+20140522*, where *20140522* is the exact revision of the *prediction:v1.6* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *prediction* crate version *0.1.7+20140522*, where *20140522* is the exact revision of the *prediction:v1.6* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *prediction* *v1d6* API can be found at the //! [official documentation site](https://developers.google.com/prediction/docs/developer-guide). @@ -168,7 +168,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -177,7 +177,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -193,6 +192,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -327,7 +327,7 @@ impl<'a, C, A> Prediction<C, A> Prediction { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -339,7 +339,7 @@ impl<'a, C, A> Prediction<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1173,7 +1173,7 @@ impl<'a, C, A> TrainedmodelGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1195,7 +1195,7 @@ impl<'a, C, A> TrainedmodelGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1375,6 +1375,7 @@ impl<'a, C, A> TrainedmodelUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Insert2)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1431,11 +1432,20 @@ impl<'a, C, A> TrainedmodelUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1458,7 +1468,7 @@ impl<'a, C, A> TrainedmodelUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1707,7 +1717,7 @@ impl<'a, C, A> TrainedmodelListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1729,7 +1739,7 @@ impl<'a, C, A> TrainedmodelListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1961,7 +1971,7 @@ impl<'a, C, A> TrainedmodelDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1983,7 +1993,7 @@ impl<'a, C, A> TrainedmodelDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2152,6 +2162,7 @@ impl<'a, C, A> TrainedmodelInsertCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Insert2)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2207,11 +2218,20 @@ impl<'a, C, A> TrainedmodelInsertCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2234,7 +2254,7 @@ impl<'a, C, A> TrainedmodelInsertCall<'a, C, A> where C: BorrowMut<hyper::Client request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2465,7 +2485,7 @@ impl<'a, C, A> TrainedmodelAnalyzeCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2487,7 +2507,7 @@ impl<'a, C, A> TrainedmodelAnalyzeCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2667,6 +2687,7 @@ impl<'a, C, A> TrainedmodelPredictCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Output)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2723,11 +2744,20 @@ impl<'a, C, A> TrainedmodelPredictCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2750,7 +2780,7 @@ impl<'a, C, A> TrainedmodelPredictCall<'a, C, A> where C: BorrowMut<hyper::Clien request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2942,6 +2972,7 @@ impl<'a, C, A> HostedmodelPredictCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Output)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2998,11 +3029,20 @@ impl<'a, C, A> HostedmodelPredictCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3025,7 +3065,7 @@ impl<'a, C, A> HostedmodelPredictCall<'a, C, A> where C: BorrowMut<hyper::Client request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) diff --git a/gen/pubsub1_beta2-cli/Cargo.toml b/gen/pubsub1_beta2-cli/Cargo.toml index ee18f89f70..805d81d10c 100644 --- a/gen/pubsub1_beta2-cli/Cargo.toml +++ b/gen/pubsub1_beta2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-pubsub1_beta2-cli" -version = "0.1.0+20150326" +version = "0.2.0+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with pubsub (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/pubsub1_beta2-cli" @@ -16,15 +16,14 @@ keywords = ["pubsub", "google", "cli"] name = "pubsub1-beta2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-pubsub1_beta2] path = "../pubsub1_beta2" diff --git a/gen/pubsub1_beta2-cli/README.md b/gen/pubsub1_beta2-cli/README.md index a62fb376c7..e08c70b6bc 100644 --- a/gen/pubsub1_beta2-cli/README.md +++ b/gen/pubsub1_beta2-cli/README.md @@ -12,32 +12,31 @@ If data-structures are requested, these will be returned as pretty-printed JSON, # Usage -This documentation was generated from the *pubsub* API at revision *20150326*. The CLI is at version *0.1.0*. +This documentation was generated from the *pubsub* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - pubsub1-beta2 [options] projects subscriptions-acknowledge <subscription> -r <kv>... [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects subscriptions-create <name> -r <kv>... [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects subscriptions-delete <subscription> [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects subscriptions-get <subscription> [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects subscriptions-list <project> [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects subscriptions-modify-ack-deadline <subscription> -r <kv>... [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects subscriptions-modify-push-config <subscription> -r <kv>... [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects subscriptions-pull <subscription> -r <kv>... [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects topics-create <name> -r <kv>... [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects topics-delete <topic> [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects topics-get <topic> [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects topics-list <project> [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects topics-publish <topic> -r <kv>... [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects topics-subscriptions-list <topic> [-p <v>...] [-o <out>] +pubsub1-beta2 [options] + projects + subscriptions-acknowledge <subscription> (-r <kv>)... [-p <v>]... [-o <out>] + subscriptions-create <name> (-r <kv>)... [-p <v>]... [-o <out>] + subscriptions-delete <subscription> [-p <v>]... [-o <out>] + subscriptions-get <subscription> [-p <v>]... [-o <out>] + subscriptions-list <project> [-p <v>]... [-o <out>] + subscriptions-modify-ack-deadline <subscription> (-r <kv>)... [-p <v>]... [-o <out>] + subscriptions-modify-push-config <subscription> (-r <kv>)... [-p <v>]... [-o <out>] + subscriptions-pull <subscription> (-r <kv>)... [-p <v>]... [-o <out>] + topics-create <name> (-r <kv>)... [-p <v>]... [-o <out>] + topics-delete <topic> [-p <v>]... [-o <out>] + topics-get <topic> [-p <v>]... [-o <out>] + topics-list <project> [-p <v>]... [-o <out>] + topics-publish <topic> (-r <kv>)... [-p <v>]... [-o <out>] + topics-subscriptions-list <topic> [-p <v>]... [-o <out>] pubsub1-beta2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/pubsub1_beta2-cli/mkdocs.yml b/gen/pubsub1_beta2-cli/mkdocs.yml index bc50e18aff..5583c9beaf 100644 --- a/gen/pubsub1_beta2-cli/mkdocs.yml +++ b/gen/pubsub1_beta2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: pubsub v0.1.0+20150326 +site_name: pubsub v0.2.0+20150326 site_url: http://byron.github.io/google-apis-rs/google-pubsub1_beta2-cli site_description: Write integrating applications with bcore diff --git a/gen/pubsub1_beta2-cli/src/cmn.rs b/gen/pubsub1_beta2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/pubsub1_beta2-cli/src/cmn.rs +++ b/gen/pubsub1_beta2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/pubsub1_beta2-cli/src/main.rs b/gen/pubsub1_beta2-cli/src/main.rs index 18bdd1d6ce..0293438ec8 100644 --- a/gen/pubsub1_beta2-cli/src/main.rs +++ b/gen/pubsub1_beta2-cli/src/main.rs @@ -2,82 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_pubsub1_beta2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - pubsub1-beta2 [options] projects subscriptions-acknowledge <subscription> -r <kv>... [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects subscriptions-create <name> -r <kv>... [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects subscriptions-delete <subscription> [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects subscriptions-get <subscription> [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects subscriptions-list <project> [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects subscriptions-modify-ack-deadline <subscription> -r <kv>... [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects subscriptions-modify-push-config <subscription> -r <kv>... [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects subscriptions-pull <subscription> -r <kv>... [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects topics-create <name> -r <kv>... [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects topics-delete <topic> [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects topics-get <topic> [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects topics-list <project> [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects topics-publish <topic> -r <kv>... [-p <v>...] [-o <out>] - pubsub1-beta2 [options] projects topics-subscriptions-list <topic> [-p <v>...] [-o <out>] - pubsub1-beta2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Pubsub<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _projects_subscriptions_acknowledge(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _projects_subscriptions_acknowledge(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::AcknowledgeRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -99,60 +72,65 @@ impl Engine { request.ack_ids.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ack-ids"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().subscriptions_acknowledge(request, &self.opt.arg_subscription); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().subscriptions_acknowledge(request, opt.value_of("subscription").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_subscriptions_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _projects_subscriptions_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Subscription::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -196,150 +174,163 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ack-deadline-seconds", "attributes", "name", "push-config", "push-endpoint", "topic"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().subscriptions_create(request, &self.opt.arg_name); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().subscriptions_create(request, opt.value_of("name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_subscriptions_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().subscriptions_delete(&self.opt.arg_subscription); - for parg in self.opt.arg_v.iter() { + fn _projects_subscriptions_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().subscriptions_delete(opt.value_of("subscription").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_subscriptions_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().subscriptions_get(&self.opt.arg_subscription); - for parg in self.opt.arg_v.iter() { + fn _projects_subscriptions_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().subscriptions_get(opt.value_of("subscription").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_subscriptions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().subscriptions_list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _projects_subscriptions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().subscriptions_list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -348,52 +339,56 @@ impl Engine { "page-size" => { call = call.page_size(arg_from_str(value.unwrap_or("-0"), err, "page-size", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "page-size"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_subscriptions_modify_ack_deadline(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _projects_subscriptions_modify_ack_deadline(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ModifyAckDeadlineRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -415,60 +410,65 @@ impl Engine { request.ack_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ack-deadline-seconds", "ack-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().subscriptions_modify_ack_deadline(request, &self.opt.arg_subscription); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().subscriptions_modify_ack_deadline(request, opt.value_of("subscription").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_subscriptions_modify_push_config(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _projects_subscriptions_modify_push_config(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ModifyPushConfigRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -502,60 +502,65 @@ impl Engine { request.push_config.as_mut().unwrap().push_endpoint = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["attributes", "push-config", "push-endpoint"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().subscriptions_modify_push_config(request, &self.opt.arg_subscription); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().subscriptions_modify_push_config(request, opt.value_of("subscription").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_subscriptions_pull(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _projects_subscriptions_pull(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PullRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -577,60 +582,65 @@ impl Engine { request.max_messages = Some(arg_from_str(value.unwrap_or("-0"), err, "max-messages", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["max-messages", "return-immediately"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().subscriptions_pull(request, &self.opt.arg_subscription); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().subscriptions_pull(request, opt.value_of("subscription").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_topics_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _projects_topics_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Topic::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -649,150 +659,163 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().topics_create(request, &self.opt.arg_name); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().topics_create(request, opt.value_of("name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_topics_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().topics_delete(&self.opt.arg_topic); - for parg in self.opt.arg_v.iter() { + fn _projects_topics_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().topics_delete(opt.value_of("topic").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_topics_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().topics_get(&self.opt.arg_topic); - for parg in self.opt.arg_v.iter() { + fn _projects_topics_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().topics_get(opt.value_of("topic").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_topics_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().topics_list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _projects_topics_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().topics_list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -801,52 +824,56 @@ impl Engine { "page-size" => { call = call.page_size(arg_from_str(value.unwrap_or("-0"), err, "page-size", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "page-size"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_topics_publish(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _projects_topics_publish(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PublishRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -862,58 +889,63 @@ impl Engine { } match &temp_cursor.to_string()[..] { _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec![]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.projects().topics_publish(request, &self.opt.arg_topic); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.projects().topics_publish(request, opt.value_of("topic").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _projects_topics_subscriptions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.projects().topics_subscriptions_list(&self.opt.arg_topic); - for parg in self.opt.arg_v.iter() { + fn _projects_topics_subscriptions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.projects().topics_subscriptions_list(opt.value_of("topic").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -922,99 +954,125 @@ impl Engine { "page-size" => { call = call.page_size(arg_from_str(value.unwrap_or("-0"), err, "page-size", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "page-size"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_projects { - if self.opt.cmd_subscriptions_acknowledge { - call_result = self._projects_subscriptions_acknowledge(dry_run, &mut err); - } else if self.opt.cmd_subscriptions_create { - call_result = self._projects_subscriptions_create(dry_run, &mut err); - } else if self.opt.cmd_subscriptions_delete { - call_result = self._projects_subscriptions_delete(dry_run, &mut err); - } else if self.opt.cmd_subscriptions_get { - call_result = self._projects_subscriptions_get(dry_run, &mut err); - } else if self.opt.cmd_subscriptions_list { - call_result = self._projects_subscriptions_list(dry_run, &mut err); - } else if self.opt.cmd_subscriptions_modify_ack_deadline { - call_result = self._projects_subscriptions_modify_ack_deadline(dry_run, &mut err); - } else if self.opt.cmd_subscriptions_modify_push_config { - call_result = self._projects_subscriptions_modify_push_config(dry_run, &mut err); - } else if self.opt.cmd_subscriptions_pull { - call_result = self._projects_subscriptions_pull(dry_run, &mut err); - } else if self.opt.cmd_topics_create { - call_result = self._projects_topics_create(dry_run, &mut err); - } else if self.opt.cmd_topics_delete { - call_result = self._projects_topics_delete(dry_run, &mut err); - } else if self.opt.cmd_topics_get { - call_result = self._projects_topics_get(dry_run, &mut err); - } else if self.opt.cmd_topics_list { - call_result = self._projects_topics_list(dry_run, &mut err); - } else if self.opt.cmd_topics_publish { - call_result = self._projects_topics_publish(dry_run, &mut err); - } else if self.opt.cmd_topics_subscriptions_list { - call_result = self._projects_topics_subscriptions_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("projects", Some(opt)) => { + match opt.subcommand() { + ("subscriptions-acknowledge", Some(opt)) => { + call_result = self._projects_subscriptions_acknowledge(opt, dry_run, &mut err); + }, + ("subscriptions-create", Some(opt)) => { + call_result = self._projects_subscriptions_create(opt, dry_run, &mut err); + }, + ("subscriptions-delete", Some(opt)) => { + call_result = self._projects_subscriptions_delete(opt, dry_run, &mut err); + }, + ("subscriptions-get", Some(opt)) => { + call_result = self._projects_subscriptions_get(opt, dry_run, &mut err); + }, + ("subscriptions-list", Some(opt)) => { + call_result = self._projects_subscriptions_list(opt, dry_run, &mut err); + }, + ("subscriptions-modify-ack-deadline", Some(opt)) => { + call_result = self._projects_subscriptions_modify_ack_deadline(opt, dry_run, &mut err); + }, + ("subscriptions-modify-push-config", Some(opt)) => { + call_result = self._projects_subscriptions_modify_push_config(opt, dry_run, &mut err); + }, + ("subscriptions-pull", Some(opt)) => { + call_result = self._projects_subscriptions_pull(opt, dry_run, &mut err); + }, + ("topics-create", Some(opt)) => { + call_result = self._projects_topics_create(opt, dry_run, &mut err); + }, + ("topics-delete", Some(opt)) => { + call_result = self._projects_topics_delete(opt, dry_run, &mut err); + }, + ("topics-get", Some(opt)) => { + call_result = self._projects_topics_get(opt, dry_run, &mut err); + }, + ("topics-list", Some(opt)) => { + call_result = self._projects_topics_list(opt, dry_run, &mut err); + }, + ("topics-publish", Some(opt)) => { + call_result = self._projects_topics_publish(opt, dry_run, &mut err); + }, + ("topics-subscriptions-list", Some(opt)) => { + call_result = self._projects_topics_subscriptions_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("projects".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -1027,7 +1085,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1040,7 +1098,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1050,37 +1108,476 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Pubsub::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("projects", "methods: 'subscriptions-acknowledge', 'subscriptions-create', 'subscriptions-delete', 'subscriptions-get', 'subscriptions-list', 'subscriptions-modify-ack-deadline', 'subscriptions-modify-push-config', 'subscriptions-pull', 'topics-create', 'topics-delete', 'topics-get', 'topics-list', 'topics-publish' and 'topics-subscriptions-list'", vec![ + ("subscriptions-acknowledge", + Some(r##"Acknowledges the messages associated with the ack tokens in the AcknowledgeRequest. The Pub/Sub system can remove the relevant messages from the subscription. Acknowledging a message whose ack deadline has expired may succeed, but such a message may be redelivered later. Acknowledging a message more than once will not result in an error."##), + "Details at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/projects_subscriptions-acknowledge", + vec![ + (Some(r##"subscription"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("subscriptions-create", + Some(r##"Creates a subscription to a given topic for a given subscriber. If the subscription already exists, returns ALREADY_EXISTS. If the corresponding topic doesn't exist, returns NOT_FOUND. If the name is not provided in the request, the server will assign a random name for this subscription on the same project as the topic."##), + "Details at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/projects_subscriptions-create", + vec![ + (Some(r##"name"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("subscriptions-delete", + Some(r##"Deletes an existing subscription. All pending messages in the subscription are immediately dropped. Calls to Pull after deletion will return NOT_FOUND. After a subscription is deleted, a new one may be created with the same name, but the new one has no association with the old subscription, or its topic unless the same topic is specified."##), + "Details at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/projects_subscriptions-delete", + vec![ + (Some(r##"subscription"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("subscriptions-get", + Some(r##"Gets the configuration details of a subscription."##), + "Details at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/projects_subscriptions-get", + vec![ + (Some(r##"subscription"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("subscriptions-list", + Some(r##"Lists matching subscriptions."##), + "Details at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/projects_subscriptions-list", + vec![ + (Some(r##"project"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("subscriptions-modify-ack-deadline", + Some(r##"Modifies the ack deadline for a specific message. This method is useful to indicate that more time is needed to process a message by the subscriber, or to make the message available for redelivery if the processing was interrupted."##), + "Details at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/projects_subscriptions-modify-ack-deadline", + vec![ + (Some(r##"subscription"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("subscriptions-modify-push-config", + Some(r##"Modifies the PushConfig for a specified subscription. This may be used to change a push subscription to a pull one (signified by an empty PushConfig) or vice versa, or change the endpoint URL and other attributes of a push subscription. Messages will accumulate for delivery continuously through the call regardless of changes to the PushConfig."##), + "Details at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/projects_subscriptions-modify-push-config", + vec![ + (Some(r##"subscription"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("subscriptions-pull", + Some(r##"Pulls messages from the server. Returns an empty list if there are no messages available in the backlog. The server may return UNAVAILABLE if there are too many concurrent pull requests pending for the given subscription."##), + "Details at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/projects_subscriptions-pull", + vec![ + (Some(r##"subscription"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("topics-create", + Some(r##"Creates the given topic with the given name."##), + "Details at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/projects_topics-create", + vec![ + (Some(r##"name"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("topics-delete", + Some(r##"Deletes the topic with the given name. Returns NOT_FOUND if the topic does not exist. After a topic is deleted, a new topic may be created with the same name; this is an entirely new topic with none of the old configuration or subscriptions. Existing subscriptions to this topic are not deleted."##), + "Details at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/projects_topics-delete", + vec![ + (Some(r##"topic"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("topics-get", + Some(r##"Gets the configuration of a topic."##), + "Details at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/projects_topics-get", + vec![ + (Some(r##"topic"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("topics-list", + Some(r##"Lists matching topics."##), + "Details at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/projects_topics-list", + vec![ + (Some(r##"project"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("topics-publish", + Some(r##"Adds one or more messages to the topic. Returns NOT_FOUND if the topic does not exist."##), + "Details at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/projects_topics-publish", + vec![ + (Some(r##"topic"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("topics-subscriptions-list", + Some(r##"Lists the name of the subscriptions for this topic."##), + "Details at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli/projects_topics-subscriptions-list", + vec![ + (Some(r##"topic"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("pubsub1-beta2") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150326") + .about("Provides reliable, many-to-many, asynchronous messaging between applications.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_pubsub1_beta2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/pubsub1_beta2/Cargo.toml b/gen/pubsub1_beta2/Cargo.toml index 087f49471c..289088405d 100644 --- a/gen/pubsub1_beta2/Cargo.toml +++ b/gen/pubsub1_beta2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-pubsub1_beta2" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with pubsub (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/pubsub1_beta2" @@ -14,9 +14,10 @@ keywords = ["pubsub", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/pubsub1_beta2/README.md b/gen/pubsub1_beta2/README.md index ac8a7a54f9..c09453f907 100644 --- a/gen/pubsub1_beta2/README.md +++ b/gen/pubsub1_beta2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-pubsub1_beta2` library allows access to all features of the *Google pubsub* service. -This documentation was generated from *pubsub* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *pubsub:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *pubsub* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *pubsub:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. # Features Handle the following *Resources* with ease from the central [hub](http://byron.github.io/google-apis-rs/google_pubsub1_beta2/struct.Pubsub.html) ... @@ -164,7 +164,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_pubsub1_beta2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_pubsub1_beta2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/pubsub1_beta2/src/cmn.rs b/gen/pubsub1_beta2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/pubsub1_beta2/src/cmn.rs +++ b/gen/pubsub1_beta2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/pubsub1_beta2/src/lib.rs b/gen/pubsub1_beta2/src/lib.rs index 1a1d79e2f4..2e0a7d46ab 100644 --- a/gen/pubsub1_beta2/src/lib.rs +++ b/gen/pubsub1_beta2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *pubsub* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *pubsub:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *pubsub* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *pubsub:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! The original source code is [on github](https://github.com/Byron/google-apis-rs/tree/master/gen/pubsub1_beta2). //! # Features //! @@ -165,7 +165,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -174,7 +174,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -190,6 +189,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -316,7 +316,7 @@ impl<'a, C, A> Pubsub<C, A> Pubsub { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -325,7 +325,7 @@ impl<'a, C, A> Pubsub<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1083,7 +1083,7 @@ impl<'a, C, A> ProjectTopicListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1105,7 +1105,7 @@ impl<'a, C, A> ProjectTopicListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1286,6 +1286,7 @@ impl<'a, C, A> ProjectSubscriptionPullCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PullResponse)> { use url::percent_encoding::{percent_encode, FORM_URLENCODED_ENCODE_SET}; + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1344,11 +1345,20 @@ impl<'a, C, A> ProjectSubscriptionPullCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1371,7 +1381,7 @@ impl<'a, C, A> ProjectSubscriptionPullCall<'a, C, A> where C: BorrowMut<hyper::C request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1552,6 +1562,7 @@ impl<'a, C, A> ProjectTopicCreateCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Topic)> { use url::percent_encoding::{percent_encode, FORM_URLENCODED_ENCODE_SET}; + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1610,11 +1621,20 @@ impl<'a, C, A> ProjectTopicCreateCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1637,7 +1657,7 @@ impl<'a, C, A> ProjectTopicCreateCall<'a, C, A> where C: BorrowMut<hyper::Client request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1869,7 +1889,7 @@ impl<'a, C, A> ProjectTopicDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1891,7 +1911,7 @@ impl<'a, C, A> ProjectTopicDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2060,6 +2080,7 @@ impl<'a, C, A> ProjectSubscriptionModifyPushConfigCall<'a, C, A> where C: Borrow /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Empty)> { use url::percent_encoding::{percent_encode, FORM_URLENCODED_ENCODE_SET}; + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2118,11 +2139,20 @@ impl<'a, C, A> ProjectSubscriptionModifyPushConfigCall<'a, C, A> where C: Borrow if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2145,7 +2175,7 @@ impl<'a, C, A> ProjectSubscriptionModifyPushConfigCall<'a, C, A> where C: Borrow request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2326,6 +2356,7 @@ impl<'a, C, A> ProjectTopicPublishCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PublishResponse)> { use url::percent_encoding::{percent_encode, FORM_URLENCODED_ENCODE_SET}; + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2384,11 +2415,20 @@ impl<'a, C, A> ProjectTopicPublishCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2411,7 +2451,7 @@ impl<'a, C, A> ProjectTopicPublishCall<'a, C, A> where C: BorrowMut<hyper::Clien request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2643,7 +2683,7 @@ impl<'a, C, A> ProjectTopicGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2665,7 +2705,7 @@ impl<'a, C, A> ProjectTopicGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2834,6 +2874,7 @@ impl<'a, C, A> ProjectSubscriptionModifyAckDeadlineCall<'a, C, A> where C: Borro /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Empty)> { use url::percent_encoding::{percent_encode, FORM_URLENCODED_ENCODE_SET}; + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2892,11 +2933,20 @@ impl<'a, C, A> ProjectSubscriptionModifyAckDeadlineCall<'a, C, A> where C: Borro if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2919,7 +2969,7 @@ impl<'a, C, A> ProjectSubscriptionModifyAckDeadlineCall<'a, C, A> where C: Borro request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3100,6 +3150,7 @@ impl<'a, C, A> ProjectSubscriptionAcknowledgeCall<'a, C, A> where C: BorrowMut<h /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Empty)> { use url::percent_encoding::{percent_encode, FORM_URLENCODED_ENCODE_SET}; + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3158,11 +3209,20 @@ impl<'a, C, A> ProjectSubscriptionAcknowledgeCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3185,7 +3245,7 @@ impl<'a, C, A> ProjectSubscriptionAcknowledgeCall<'a, C, A> where C: BorrowMut<h request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3417,7 +3477,7 @@ impl<'a, C, A> ProjectSubscriptionDeleteCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3439,7 +3499,7 @@ impl<'a, C, A> ProjectSubscriptionDeleteCall<'a, C, A> where C: BorrowMut<hyper: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3608,6 +3668,7 @@ impl<'a, C, A> ProjectSubscriptionCreateCall<'a, C, A> where C: BorrowMut<hyper: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Subscription)> { use url::percent_encoding::{percent_encode, FORM_URLENCODED_ENCODE_SET}; + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3666,11 +3727,20 @@ impl<'a, C, A> ProjectSubscriptionCreateCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3693,7 +3763,7 @@ impl<'a, C, A> ProjectSubscriptionCreateCall<'a, C, A> where C: BorrowMut<hyper: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3925,7 +3995,7 @@ impl<'a, C, A> ProjectSubscriptionGetCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3947,7 +4017,7 @@ impl<'a, C, A> ProjectSubscriptionGetCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4177,7 +4247,7 @@ impl<'a, C, A> ProjectTopicSubscriptionListCall<'a, C, A> where C: BorrowMut<hyp if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4199,7 +4269,7 @@ impl<'a, C, A> ProjectTopicSubscriptionListCall<'a, C, A> where C: BorrowMut<hyp access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4441,7 +4511,7 @@ impl<'a, C, A> ProjectSubscriptionListCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4463,7 +4533,7 @@ impl<'a, C, A> ProjectSubscriptionListCall<'a, C, A> where C: BorrowMut<hyper::C access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/qpxexpress1-cli/Cargo.toml b/gen/qpxexpress1-cli/Cargo.toml index d6b4a73bed..ac786cdeec 100644 --- a/gen/qpxexpress1-cli/Cargo.toml +++ b/gen/qpxexpress1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-qpxexpress1-cli" -version = "0.1.0+20140321" +version = "0.2.0+20140321" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with QPX Express (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/qpxexpress1-cli" @@ -17,15 +17,14 @@ keywords = ["qpxExpress", "google", "cli"] name = "qpxexpress1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-qpxexpress1] path = "../qpxexpress1" diff --git a/gen/qpxexpress1-cli/README.md b/gen/qpxexpress1-cli/README.md index 87ca65ea9d..800d938585 100644 --- a/gen/qpxexpress1-cli/README.md +++ b/gen/qpxexpress1-cli/README.md @@ -10,17 +10,19 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *QPX Express* API can be found at the +[official documentation site](http://developers.google.com/qpx-express). + # Usage -This documentation was generated from the *QPX Express* API at revision *20140321*. The CLI is at version *0.1.0*. +This documentation was generated from the *QPX Express* API at revision *20140321*. The CLI is at version *0.2.0*. ```bash - qpxexpress1 [options] trips search -r <kv>... [-p <v>...] [-o <out>] +qpxexpress1 [options] + trips + search (-r <kv>)... [-p <v>]... [-o <out>] qpxexpress1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_qpxexpress1_cli/index.html - Configuration: --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/qpxexpress1-cli/mkdocs.yml b/gen/qpxexpress1-cli/mkdocs.yml index a141bef20b..8da408a14c 100644 --- a/gen/qpxexpress1-cli/mkdocs.yml +++ b/gen/qpxexpress1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: QPX Express v0.1.0+20140321 +site_name: QPX Express v0.2.0+20140321 site_url: http://byron.github.io/google-apis-rs/google-qpxexpress1-cli site_description: Write integrating applications with bcore diff --git a/gen/qpxexpress1-cli/src/cmn.rs b/gen/qpxexpress1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/qpxexpress1-cli/src/cmn.rs +++ b/gen/qpxexpress1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/qpxexpress1-cli/src/main.rs b/gen/qpxexpress1-cli/src/main.rs index ec10a38698..64f01b16e1 100644 --- a/gen/qpxexpress1-cli/src/main.rs +++ b/gen/qpxexpress1-cli/src/main.rs @@ -2,65 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_qpxexpress1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - qpxexpress1 [options] trips search -r <kv>... [-p <v>...] [-o <out>] - qpxexpress1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_qpxexpress1_cli/index.html - -Configuration: - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::QPXExpress<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _trips_search(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _trips_search(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TripsSearchRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -129,78 +119,92 @@ impl Engine { request.request.as_mut().unwrap().max_price = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["adult-count", "child-count", "infant-in-lap-count", "infant-in-seat-count", "kind", "max-price", "passengers", "refundable", "request", "sale-country", "senior-count", "solutions"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.trips().search(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_trips { - if self.opt.cmd_search { - call_result = self._trips_search(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("trips", Some(opt)) => { + match opt.subcommand() { + ("search", Some(opt)) => { + call_result = self._trips_search(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("trips".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -213,7 +217,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -226,7 +230,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -236,37 +240,143 @@ impl Engine { let engine = Engine { opt: opt, hub: api::QPXExpress::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("trips", "methods: 'search'", vec![ + ("search", + Some(r##"Returns a list of flights."##), + "Details at http://byron.github.io/google-apis-rs/google_qpxexpress1_cli/trips_search", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("qpxexpress1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20140321") + .about("Lets you find the least expensive flights between an origin and a destination.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_qpxexpress1_cli") + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/qpxexpress1/Cargo.toml b/gen/qpxexpress1/Cargo.toml index ff177f53ea..24a7a1b1d6 100644 --- a/gen/qpxexpress1/Cargo.toml +++ b/gen/qpxexpress1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-qpxexpress1" -version = "0.1.6+20140321" +version = "0.1.7+20140321" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with QPX Express (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/qpxexpress1" @@ -15,9 +15,10 @@ keywords = ["qpxExpress", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/qpxexpress1/README.md b/gen/qpxexpress1/README.md index 317e67cf76..c0f37988c6 100644 --- a/gen/qpxexpress1/README.md +++ b/gen/qpxexpress1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-qpxexpress1` library allows access to all features of the *Google QPX Express* service. -This documentation was generated from *QPX Express* crate version *0.1.6+20140321*, where *20140321* is the exact revision of the *qpxExpress:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *QPX Express* crate version *0.1.7+20140321*, where *20140321* is the exact revision of the *qpxExpress:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *QPX Express* *v1* API can be found at the [official documentation site](http://developers.google.com/qpx-express). @@ -163,7 +163,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_qpxexpress1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_qpxexpress1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/qpxexpress1/src/cmn.rs b/gen/qpxexpress1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/qpxexpress1/src/cmn.rs +++ b/gen/qpxexpress1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/qpxexpress1/src/lib.rs b/gen/qpxexpress1/src/lib.rs index 0904a6e8b1..bead8d2275 100644 --- a/gen/qpxexpress1/src/lib.rs +++ b/gen/qpxexpress1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *QPX Express* crate version *0.1.6+20140321*, where *20140321* is the exact revision of the *qpxExpress:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *QPX Express* crate version *0.1.7+20140321*, where *20140321* is the exact revision of the *qpxExpress:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *QPX Express* *v1* API can be found at the //! [official documentation site](http://developers.google.com/qpx-express). @@ -164,7 +164,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -173,7 +173,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -189,6 +188,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -289,7 +289,7 @@ impl<'a, C, A> QPXExpress<C, A> QPXExpress { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -298,7 +298,7 @@ impl<'a, C, A> QPXExpress<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1025,6 +1025,7 @@ impl<'a, C, A> TripSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, TripsSearchResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1064,11 +1065,20 @@ impl<'a, C, A> TripSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1077,7 +1087,7 @@ impl<'a, C, A> TripSearchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) diff --git a/gen/replicapool1_beta2-cli/Cargo.toml b/gen/replicapool1_beta2-cli/Cargo.toml index f15a17f723..3afecda823 100644 --- a/gen/replicapool1_beta2-cli/Cargo.toml +++ b/gen/replicapool1_beta2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-replicapool1_beta2-cli" -version = "0.1.0+20150223" +version = "0.2.0+20150223" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with replicapool (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/replicapool1_beta2-cli" @@ -17,15 +17,14 @@ keywords = ["replicapool", "google", "cli"] name = "replicapool1-beta2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-replicapool1_beta2] path = "../replicapool1_beta2" diff --git a/gen/replicapool1_beta2-cli/README.md b/gen/replicapool1_beta2-cli/README.md index d71c1d398e..8e73c267b9 100644 --- a/gen/replicapool1_beta2-cli/README.md +++ b/gen/replicapool1_beta2-cli/README.md @@ -10,32 +10,35 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *replicapool* API can be found at the +[official documentation site](https://developers.google.com/compute/docs/instance-groups/manager/v1beta2). + # Usage -This documentation was generated from the *replicapool* API at revision *20150223*. The CLI is at version *0.1.0*. +This documentation was generated from the *replicapool* API at revision *20150223*. The CLI is at version *0.2.0*. ```bash - replicapool1-beta2 [options] instance-group-managers abandon-instances <project> <zone> <instance-group-manager> -r <kv>... [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers delete <project> <zone> <instance-group-manager> [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers delete-instances <project> <zone> <instance-group-manager> -r <kv>... [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers get <project> <zone> <instance-group-manager> [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers insert <project> <zone> <size> -r <kv>... [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers list <project> <zone> [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers recreate-instances <project> <zone> <instance-group-manager> -r <kv>... [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers resize <project> <zone> <instance-group-manager> <size> [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers set-instance-template <project> <zone> <instance-group-manager> -r <kv>... [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers set-target-pools <project> <zone> <instance-group-manager> -r <kv>... [-p <v>...] [-o <out>] - replicapool1-beta2 [options] zone-operations get <project> <zone> <operation> [-p <v>...] [-o <out>] - replicapool1-beta2 [options] zone-operations list <project> <zone> [-p <v>...] [-o <out>] +replicapool1-beta2 [options] + instance-group-managers + abandon-instances <project> <zone> <instance-group-manager> (-r <kv>)... [-p <v>]... [-o <out>] + delete <project> <zone> <instance-group-manager> [-p <v>]... [-o <out>] + delete-instances <project> <zone> <instance-group-manager> (-r <kv>)... [-p <v>]... [-o <out>] + get <project> <zone> <instance-group-manager> [-p <v>]... [-o <out>] + insert <project> <zone> <size> (-r <kv>)... [-p <v>]... [-o <out>] + list <project> <zone> [-p <v>]... [-o <out>] + recreate-instances <project> <zone> <instance-group-manager> (-r <kv>)... [-p <v>]... [-o <out>] + resize <project> <zone> <instance-group-manager> <size> [-p <v>]... [-o <out>] + set-instance-template <project> <zone> <instance-group-manager> (-r <kv>)... [-p <v>]... [-o <out>] + set-target-pools <project> <zone> <instance-group-manager> (-r <kv>)... [-p <v>]... [-o <out>] + zone-operations + get <project> <zone> <operation> [-p <v>]... [-o <out>] + list <project> <zone> [-p <v>]... [-o <out>] replicapool1-beta2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/replicapool1_beta2-cli/mkdocs.yml b/gen/replicapool1_beta2-cli/mkdocs.yml index f8c0f3dad2..662cb5a745 100644 --- a/gen/replicapool1_beta2-cli/mkdocs.yml +++ b/gen/replicapool1_beta2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: replicapool v0.1.0+20150223 +site_name: replicapool v0.2.0+20150223 site_url: http://byron.github.io/google-apis-rs/google-replicapool1_beta2-cli site_description: Write integrating applications with bcore diff --git a/gen/replicapool1_beta2-cli/src/cmn.rs b/gen/replicapool1_beta2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/replicapool1_beta2-cli/src/cmn.rs +++ b/gen/replicapool1_beta2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/replicapool1_beta2-cli/src/main.rs b/gen/replicapool1_beta2-cli/src/main.rs index 37d9ed480b..0f7acf383b 100644 --- a/gen/replicapool1_beta2-cli/src/main.rs +++ b/gen/replicapool1_beta2-cli/src/main.rs @@ -2,80 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_replicapool1_beta2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - replicapool1-beta2 [options] instance-group-managers abandon-instances <project> <zone> <instance-group-manager> -r <kv>... [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers delete <project> <zone> <instance-group-manager> [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers delete-instances <project> <zone> <instance-group-manager> -r <kv>... [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers get <project> <zone> <instance-group-manager> [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers insert <project> <zone> <size> -r <kv>... [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers list <project> <zone> [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers recreate-instances <project> <zone> <instance-group-manager> -r <kv>... [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers resize <project> <zone> <instance-group-manager> <size> [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers set-instance-template <project> <zone> <instance-group-manager> -r <kv>... [-p <v>...] [-o <out>] - replicapool1-beta2 [options] instance-group-managers set-target-pools <project> <zone> <instance-group-manager> -r <kv>... [-p <v>...] [-o <out>] - replicapool1-beta2 [options] zone-operations get <project> <zone> <operation> [-p <v>...] [-o <out>] - replicapool1-beta2 [options] zone-operations list <project> <zone> [-p <v>...] [-o <out>] - replicapool1-beta2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Replicapool<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _instance_group_managers_abandon_instances(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _instance_group_managers_abandon_instances(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InstanceGroupManagersAbandonInstancesRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -97,106 +72,115 @@ impl Engine { request.instances.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["instances"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instance_group_managers().abandon_instances(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance_group_manager); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instance_group_managers().abandon_instances(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance-group-manager").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instance_group_managers_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.instance_group_managers().delete(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance_group_manager); - for parg in self.opt.arg_v.iter() { + fn _instance_group_managers_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instance_group_managers().delete(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance-group-manager").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instance_group_managers_delete_instances(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _instance_group_managers_delete_instances(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InstanceGroupManagersDeleteInstancesRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -218,106 +202,115 @@ impl Engine { request.instances.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["instances"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instance_group_managers().delete_instances(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance_group_manager); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instance_group_managers().delete_instances(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance-group-manager").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instance_group_managers_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.instance_group_managers().get(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance_group_manager); - for parg in self.opt.arg_v.iter() { + fn _instance_group_managers_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instance_group_managers().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance-group-manager").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instance_group_managers_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _instance_group_managers_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InstanceGroupManager::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -375,59 +368,64 @@ impl Engine { request.current_size = Some(arg_from_str(value.unwrap_or("-0"), err, "current-size", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["base-instance-name", "creation-timestamp", "current-size", "description", "fingerprint", "group", "id", "instance-template", "kind", "name", "self-link", "target-pools", "target-size"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let size: i32 = arg_from_str(&self.opt.arg_size, err, "<size>", "integer"); - let mut call = self.hub.instance_group_managers().insert(request, &self.opt.arg_project, &self.opt.arg_zone, size); - for parg in self.opt.arg_v.iter() { + let size: i32 = arg_from_str(&opt.value_of("size").unwrap_or(""), err, "<size>", "integer"); + let mut call = self.hub.instance_group_managers().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), size); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instance_group_managers_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.instance_group_managers().list(&self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + fn _instance_group_managers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instance_group_managers().list(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -439,52 +437,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instance_group_managers_recreate_instances(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _instance_group_managers_recreate_instances(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InstanceGroupManagersRecreateInstancesRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -506,107 +508,116 @@ impl Engine { request.instances.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["instances"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instance_group_managers().recreate_instances(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance_group_manager); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instance_group_managers().recreate_instances(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance-group-manager").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instance_group_managers_resize(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let size: i32 = arg_from_str(&self.opt.arg_size, err, "<size>", "integer"); - let mut call = self.hub.instance_group_managers().resize(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance_group_manager, size); - for parg in self.opt.arg_v.iter() { + fn _instance_group_managers_resize(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let size: i32 = arg_from_str(&opt.value_of("size").unwrap_or(""), err, "<size>", "integer"); + let mut call = self.hub.instance_group_managers().resize(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance-group-manager").unwrap_or(""), size); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instance_group_managers_set_instance_template(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _instance_group_managers_set_instance_template(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InstanceGroupManagersSetInstanceTemplateRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -625,60 +636,65 @@ impl Engine { request.instance_template = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["instance-template"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instance_group_managers().set_instance_template(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance_group_manager); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instance_group_managers().set_instance_template(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance-group-manager").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instance_group_managers_set_target_pools(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _instance_group_managers_set_target_pools(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InstanceGroupManagersSetTargetPoolsRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -703,104 +719,113 @@ impl Engine { request.fingerprint = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["fingerprint", "target-pools"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instance_group_managers().set_target_pools(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_instance_group_manager); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instance_group_managers().set_target_pools(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("instance-group-manager").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_operations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.zone_operations().get(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_operation); - for parg in self.opt.arg_v.iter() { + fn _zone_operations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_operations().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("operation").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_operations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.zone_operations().list(&self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + fn _zone_operations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_operations().list(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -812,100 +837,127 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_instance_group_managers { - if self.opt.cmd_abandon_instances { - call_result = self._instance_group_managers_abandon_instances(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._instance_group_managers_delete(dry_run, &mut err); - } else if self.opt.cmd_delete_instances { - call_result = self._instance_group_managers_delete_instances(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._instance_group_managers_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._instance_group_managers_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._instance_group_managers_list(dry_run, &mut err); - } else if self.opt.cmd_recreate_instances { - call_result = self._instance_group_managers_recreate_instances(dry_run, &mut err); - } else if self.opt.cmd_resize { - call_result = self._instance_group_managers_resize(dry_run, &mut err); - } else if self.opt.cmd_set_instance_template { - call_result = self._instance_group_managers_set_instance_template(dry_run, &mut err); - } else if self.opt.cmd_set_target_pools { - call_result = self._instance_group_managers_set_target_pools(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("instance-group-managers", Some(opt)) => { + match opt.subcommand() { + ("abandon-instances", Some(opt)) => { + call_result = self._instance_group_managers_abandon_instances(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._instance_group_managers_delete(opt, dry_run, &mut err); + }, + ("delete-instances", Some(opt)) => { + call_result = self._instance_group_managers_delete_instances(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._instance_group_managers_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._instance_group_managers_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._instance_group_managers_list(opt, dry_run, &mut err); + }, + ("recreate-instances", Some(opt)) => { + call_result = self._instance_group_managers_recreate_instances(opt, dry_run, &mut err); + }, + ("resize", Some(opt)) => { + call_result = self._instance_group_managers_resize(opt, dry_run, &mut err); + }, + ("set-instance-template", Some(opt)) => { + call_result = self._instance_group_managers_set_instance_template(opt, dry_run, &mut err); + }, + ("set-target-pools", Some(opt)) => { + call_result = self._instance_group_managers_set_target_pools(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("instance-group-managers".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("zone-operations", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._zone_operations_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._zone_operations_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("zone-operations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_zone_operations { - if self.opt.cmd_get { - call_result = self._zone_operations_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._zone_operations_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -918,7 +970,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -931,7 +983,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -941,37 +993,567 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Replicapool::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("instance-group-managers", "methods: 'abandon-instances', 'delete', 'delete-instances', 'get', 'insert', 'list', 'recreate-instances', 'resize', 'set-instance-template' and 'set-target-pools'", vec![ + ("abandon-instances", + Some(r##"Removes the specified instances from the managed instance group, and from any target pools of which they were members, without deleting the instances."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli/instance-group-managers_abandon-instances", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the instance group manager resides."##), + Some(true), + Some(false)), + + (Some(r##"instance-group-manager"##), + None, + Some(r##"The name of the instance group manager."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes the instance group manager and all instances contained within. If you'd like to delete the manager without deleting the instances, you must first abandon the instances to remove them from the group."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli/instance-group-managers_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the instance group manager resides."##), + Some(true), + Some(false)), + + (Some(r##"instance-group-manager"##), + None, + Some(r##"Name of the Instance Group Manager resource to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete-instances", + Some(r##"Deletes the specified instances. The instances are deleted, then removed from the instance group and any target pools of which they were a member. The targetSize of the instance group manager is reduced by the number of instances deleted."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli/instance-group-managers_delete-instances", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the instance group manager resides."##), + Some(true), + Some(false)), + + (Some(r##"instance-group-manager"##), + None, + Some(r##"The name of the instance group manager."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns the specified Instance Group Manager resource."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli/instance-group-managers_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the instance group manager resides."##), + Some(true), + Some(false)), + + (Some(r##"instance-group-manager"##), + None, + Some(r##"Name of the instance resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates an instance group manager, as well as the instance group and the specified number of instances."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli/instance-group-managers_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the instance group manager resides."##), + Some(true), + Some(false)), + + (Some(r##"size"##), + None, + Some(r##"Number of instances that should exist."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of Instance Group Manager resources contained within the specified zone."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli/instance-group-managers_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the instance group manager resides."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("recreate-instances", + Some(r##"Recreates the specified instances. The instances are deleted, then recreated using the instance group manager's current instance template."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli/instance-group-managers_recreate-instances", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the instance group manager resides."##), + Some(true), + Some(false)), + + (Some(r##"instance-group-manager"##), + None, + Some(r##"The name of the instance group manager."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("resize", + Some(r##"Resizes the managed instance group up or down. If resized up, new instances are created using the current instance template. If resized down, instances are removed in the order outlined in Resizing a managed instance group."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli/instance-group-managers_resize", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the instance group manager resides."##), + Some(true), + Some(false)), + + (Some(r##"instance-group-manager"##), + None, + Some(r##"The name of the instance group manager."##), + Some(true), + Some(false)), + + (Some(r##"size"##), + None, + Some(r##"Number of instances that should exist in this Instance Group Manager."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-instance-template", + Some(r##"Sets the instance template to use when creating new instances in this group. Existing instances are not affected."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli/instance-group-managers_set-instance-template", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the instance group manager resides."##), + Some(true), + Some(false)), + + (Some(r##"instance-group-manager"##), + None, + Some(r##"The name of the instance group manager."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-target-pools", + Some(r##"Modifies the target pools to which all new instances in this group are assigned. Existing instances in the group are not affected."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli/instance-group-managers_set-target-pools", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the instance group manager resides."##), + Some(true), + Some(false)), + + (Some(r##"instance-group-manager"##), + None, + Some(r##"The name of the instance group manager."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("zone-operations", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Retrieves the specified zone-specific operation resource."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli/zone-operations_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Name of the zone scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"operation"##), + None, + Some(r##"Name of the operation resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of operation resources contained within the specified zone."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli/zone-operations_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Name of the zone scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("replicapool1-beta2") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150223") + .about("The Google Compute Engine Instance Group Manager API provides groups of homogenous Compute Engine Instances.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_replicapool1_beta2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/replicapool1_beta2/Cargo.toml b/gen/replicapool1_beta2/Cargo.toml index 5307400ad8..b2792ecab8 100644 --- a/gen/replicapool1_beta2/Cargo.toml +++ b/gen/replicapool1_beta2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-replicapool1_beta2" -version = "0.1.6+20150223" +version = "0.1.7+20150223" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with replicapool (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/replicapool1_beta2" @@ -15,9 +15,10 @@ keywords = ["replicapool", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/replicapool1_beta2/README.md b/gen/replicapool1_beta2/README.md index 58d97dd083..bee13f5229 100644 --- a/gen/replicapool1_beta2/README.md +++ b/gen/replicapool1_beta2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-replicapool1_beta2` library allows access to all features of the *Google replicapool* service. -This documentation was generated from *replicapool* crate version *0.1.6+20150223*, where *20150223* is the exact revision of the *replicapool:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *replicapool* crate version *0.1.7+20150223*, where *20150223* is the exact revision of the *replicapool:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *replicapool* *v1_beta2* API can be found at the [official documentation site](https://developers.google.com/compute/docs/instance-groups/manager/v1beta2). @@ -171,7 +171,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_replicapool1_beta2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_replicapool1_beta2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/replicapool1_beta2/src/cmn.rs b/gen/replicapool1_beta2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/replicapool1_beta2/src/cmn.rs +++ b/gen/replicapool1_beta2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/replicapool1_beta2/src/lib.rs b/gen/replicapool1_beta2/src/lib.rs index a255912332..99ee591cc1 100644 --- a/gen/replicapool1_beta2/src/lib.rs +++ b/gen/replicapool1_beta2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *replicapool* crate version *0.1.6+20150223*, where *20150223* is the exact revision of the *replicapool:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *replicapool* crate version *0.1.7+20150223*, where *20150223* is the exact revision of the *replicapool:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *replicapool* *v1_beta2* API can be found at the //! [official documentation site](https://developers.google.com/compute/docs/instance-groups/manager/v1beta2). @@ -172,7 +172,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -181,7 +181,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -197,6 +196,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -324,7 +324,7 @@ impl<'a, C, A> Replicapool<C, A> Replicapool { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -336,7 +336,7 @@ impl<'a, C, A> Replicapool<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1190,7 +1190,7 @@ impl<'a, C, A> ZoneOperationListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1212,7 +1212,7 @@ impl<'a, C, A> ZoneOperationListCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1464,7 +1464,7 @@ impl<'a, C, A> ZoneOperationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1486,7 +1486,7 @@ impl<'a, C, A> ZoneOperationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1677,6 +1677,7 @@ impl<'a, C, A> InstanceGroupManagerSetTargetPoolCall<'a, C, A> where C: BorrowMu /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1734,11 +1735,20 @@ impl<'a, C, A> InstanceGroupManagerSetTargetPoolCall<'a, C, A> where C: BorrowMu if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1761,7 +1771,7 @@ impl<'a, C, A> InstanceGroupManagerSetTargetPoolCall<'a, C, A> where C: BorrowMu request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2027,7 +2037,7 @@ impl<'a, C, A> InstanceGroupManagerListCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2049,7 +2059,7 @@ impl<'a, C, A> InstanceGroupManagerListCall<'a, C, A> where C: BorrowMut<hyper:: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2251,6 +2261,7 @@ impl<'a, C, A> InstanceGroupManagerInsertCall<'a, C, A> where C: BorrowMut<hyper /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2308,11 +2319,20 @@ impl<'a, C, A> InstanceGroupManagerInsertCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2335,7 +2355,7 @@ impl<'a, C, A> InstanceGroupManagerInsertCall<'a, C, A> where C: BorrowMut<hyper request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2588,7 +2608,7 @@ impl<'a, C, A> InstanceGroupManagerGetCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2610,7 +2630,7 @@ impl<'a, C, A> InstanceGroupManagerGetCall<'a, C, A> where C: BorrowMut<hyper::C access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2801,6 +2821,7 @@ impl<'a, C, A> InstanceGroupManagerAbandonInstanceCall<'a, C, A> where C: Borrow /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2858,11 +2879,20 @@ impl<'a, C, A> InstanceGroupManagerAbandonInstanceCall<'a, C, A> where C: Borrow if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2885,7 +2915,7 @@ impl<'a, C, A> InstanceGroupManagerAbandonInstanceCall<'a, C, A> where C: Borrow request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3088,6 +3118,7 @@ impl<'a, C, A> InstanceGroupManagerRecreateInstanceCall<'a, C, A> where C: Borro /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3145,11 +3176,20 @@ impl<'a, C, A> InstanceGroupManagerRecreateInstanceCall<'a, C, A> where C: Borro if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3172,7 +3212,7 @@ impl<'a, C, A> InstanceGroupManagerRecreateInstanceCall<'a, C, A> where C: Borro request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3425,7 +3465,7 @@ impl<'a, C, A> InstanceGroupManagerDeleteCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3447,7 +3487,7 @@ impl<'a, C, A> InstanceGroupManagerDeleteCall<'a, C, A> where C: BorrowMut<hyper access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3638,6 +3678,7 @@ impl<'a, C, A> InstanceGroupManagerSetInstanceTemplateCall<'a, C, A> where C: Bo /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3695,11 +3736,20 @@ impl<'a, C, A> InstanceGroupManagerSetInstanceTemplateCall<'a, C, A> where C: Bo if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3722,7 +3772,7 @@ impl<'a, C, A> InstanceGroupManagerSetInstanceTemplateCall<'a, C, A> where C: Bo request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3977,7 +4027,7 @@ impl<'a, C, A> InstanceGroupManagerResizeCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3999,7 +4049,7 @@ impl<'a, C, A> InstanceGroupManagerResizeCall<'a, C, A> where C: BorrowMut<hyper access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4200,6 +4250,7 @@ impl<'a, C, A> InstanceGroupManagerDeleteInstanceCall<'a, C, A> where C: BorrowM /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4257,11 +4308,20 @@ impl<'a, C, A> InstanceGroupManagerDeleteInstanceCall<'a, C, A> where C: BorrowM if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4284,7 +4344,7 @@ impl<'a, C, A> InstanceGroupManagerDeleteInstanceCall<'a, C, A> where C: BorrowM request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) diff --git a/gen/replicapoolupdater1_beta1-cli/Cargo.toml b/gen/replicapoolupdater1_beta1-cli/Cargo.toml index 888c60d793..e7e33b2c74 100644 --- a/gen/replicapoolupdater1_beta1-cli/Cargo.toml +++ b/gen/replicapoolupdater1_beta1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-replicapoolupdater1_beta1-cli" -version = "0.1.0+20150326" +version = "0.2.0+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with replicapoolupdater (protocol v1beta1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/replicapoolupdater1_beta1-cli" @@ -17,15 +17,14 @@ keywords = ["replicapoolupdater", "google", "cli"] name = "replicapoolupdater1-beta1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-replicapoolupdater1_beta1] path = "../replicapoolupdater1_beta1" diff --git a/gen/replicapoolupdater1_beta1-cli/README.md b/gen/replicapoolupdater1_beta1-cli/README.md index c662ce9df9..f5e6fb6d59 100644 --- a/gen/replicapoolupdater1_beta1-cli/README.md +++ b/gen/replicapoolupdater1_beta1-cli/README.md @@ -10,29 +10,32 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *replicapoolupdater* API can be found at the +[official documentation site](https://cloud.google.com/compute/docs/instance-groups/manager/#applying_rolling_updates_using_the_updater_service). + # Usage -This documentation was generated from the *replicapoolupdater* API at revision *20150326*. The CLI is at version *0.1.0*. +This documentation was generated from the *replicapoolupdater* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - replicapoolupdater1-beta1 [options] rolling-updates cancel <project> <zone> <rolling-update> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] rolling-updates get <project> <zone> <rolling-update> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] rolling-updates insert <project> <zone> -r <kv>... [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] rolling-updates list <project> <zone> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] rolling-updates list-instance-updates <project> <zone> <rolling-update> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] rolling-updates pause <project> <zone> <rolling-update> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] rolling-updates resume <project> <zone> <rolling-update> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] rolling-updates rollback <project> <zone> <rolling-update> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] zone-operations get <project> <zone> <operation> [-p <v>...] [-o <out>] +replicapoolupdater1-beta1 [options] + rolling-updates + cancel <project> <zone> <rolling-update> [-p <v>]... [-o <out>] + get <project> <zone> <rolling-update> [-p <v>]... [-o <out>] + insert <project> <zone> (-r <kv>)... [-p <v>]... [-o <out>] + list <project> <zone> [-p <v>]... [-o <out>] + list-instance-updates <project> <zone> <rolling-update> [-p <v>]... [-o <out>] + pause <project> <zone> <rolling-update> [-p <v>]... [-o <out>] + resume <project> <zone> <rolling-update> [-p <v>]... [-o <out>] + rollback <project> <zone> <rolling-update> [-p <v>]... [-o <out>] + zone-operations + get <project> <zone> <operation> [-p <v>]... [-o <out>] replicapoolupdater1-beta1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_replicapoolupdater1_beta1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/replicapoolupdater1_beta1-cli/mkdocs.yml b/gen/replicapoolupdater1_beta1-cli/mkdocs.yml index db8bd829ea..b8bbe99308 100644 --- a/gen/replicapoolupdater1_beta1-cli/mkdocs.yml +++ b/gen/replicapoolupdater1_beta1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: replicapoolupdater v0.1.0+20150326 +site_name: replicapoolupdater v0.2.0+20150326 site_url: http://byron.github.io/google-apis-rs/google-replicapoolupdater1_beta1-cli site_description: Write integrating applications with bcore diff --git a/gen/replicapoolupdater1_beta1-cli/src/cmn.rs b/gen/replicapoolupdater1_beta1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/replicapoolupdater1_beta1-cli/src/cmn.rs +++ b/gen/replicapoolupdater1_beta1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/replicapoolupdater1_beta1-cli/src/main.rs b/gen/replicapoolupdater1_beta1-cli/src/main.rs index 245cb5f644..9929d359c5 100644 --- a/gen/replicapoolupdater1_beta1-cli/src/main.rs +++ b/gen/replicapoolupdater1_beta1-cli/src/main.rs @@ -2,169 +2,155 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_replicapoolupdater1_beta1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - replicapoolupdater1-beta1 [options] rolling-updates cancel <project> <zone> <rolling-update> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] rolling-updates get <project> <zone> <rolling-update> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] rolling-updates insert <project> <zone> -r <kv>... [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] rolling-updates list <project> <zone> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] rolling-updates list-instance-updates <project> <zone> <rolling-update> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] rolling-updates pause <project> <zone> <rolling-update> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] rolling-updates resume <project> <zone> <rolling-update> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] rolling-updates rollback <project> <zone> <rolling-update> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 [options] zone-operations get <project> <zone> <operation> [-p <v>...] [-o <out>] - replicapoolupdater1-beta1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_replicapoolupdater1_beta1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Replicapoolupdater<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _rolling_updates_cancel(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rolling_updates().cancel(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_rolling_update); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _rolling_updates_cancel(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rolling_updates().cancel(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("rolling-update").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rolling_updates_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rolling_updates().get(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_rolling_update); - for parg in self.opt.arg_v.iter() { + fn _rolling_updates_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rolling_updates().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("rolling-update").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rolling_updates_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _rolling_updates_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::RollingUpdate::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -249,58 +235,63 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["action-type", "auto-pause-after-instances", "creation-timestamp", "description", "id", "instance-group", "instance-group-manager", "instance-startup-timeout-sec", "instance-template", "kind", "max-num-concurrent-instances", "max-num-failed-instances", "min-instance-update-time-sec", "policy", "progress", "self-link", "status", "status-message", "user"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.rolling_updates().insert(request, &self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.rolling_updates().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rolling_updates_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rolling_updates().list(&self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + fn _rolling_updates_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rolling_updates().list(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -315,50 +306,54 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results", "instance-group-manager"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rolling_updates_list_instance_updates(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rolling_updates().list_instance_updates(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_rolling_update); - for parg in self.opt.arg_v.iter() { + fn _rolling_updates_list_instance_updates(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rolling_updates().list_instance_updates(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("rolling-update").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -370,278 +365,318 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rolling_updates_pause(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rolling_updates().pause(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_rolling_update); - for parg in self.opt.arg_v.iter() { + fn _rolling_updates_pause(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rolling_updates().pause(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("rolling-update").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rolling_updates_resume(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rolling_updates().resume(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_rolling_update); - for parg in self.opt.arg_v.iter() { + fn _rolling_updates_resume(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rolling_updates().resume(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("rolling-update").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _rolling_updates_rollback(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.rolling_updates().rollback(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_rolling_update); - for parg in self.opt.arg_v.iter() { + fn _rolling_updates_rollback(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.rolling_updates().rollback(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("rolling-update").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_operations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.zone_operations().get(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_operation); - for parg in self.opt.arg_v.iter() { + fn _zone_operations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_operations().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("operation").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_rolling_updates { - if self.opt.cmd_cancel { - call_result = self._rolling_updates_cancel(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._rolling_updates_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._rolling_updates_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._rolling_updates_list(dry_run, &mut err); - } else if self.opt.cmd_list_instance_updates { - call_result = self._rolling_updates_list_instance_updates(dry_run, &mut err); - } else if self.opt.cmd_pause { - call_result = self._rolling_updates_pause(dry_run, &mut err); - } else if self.opt.cmd_resume { - call_result = self._rolling_updates_resume(dry_run, &mut err); - } else if self.opt.cmd_rollback { - call_result = self._rolling_updates_rollback(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("rolling-updates", Some(opt)) => { + match opt.subcommand() { + ("cancel", Some(opt)) => { + call_result = self._rolling_updates_cancel(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._rolling_updates_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._rolling_updates_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._rolling_updates_list(opt, dry_run, &mut err); + }, + ("list-instance-updates", Some(opt)) => { + call_result = self._rolling_updates_list_instance_updates(opt, dry_run, &mut err); + }, + ("pause", Some(opt)) => { + call_result = self._rolling_updates_pause(opt, dry_run, &mut err); + }, + ("resume", Some(opt)) => { + call_result = self._rolling_updates_resume(opt, dry_run, &mut err); + }, + ("rollback", Some(opt)) => { + call_result = self._rolling_updates_rollback(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("rolling-updates".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("zone-operations", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._zone_operations_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("zone-operations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_zone_operations { - if self.opt.cmd_get { - call_result = self._zone_operations_get(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -654,7 +689,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -667,7 +702,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -677,37 +712,429 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Replicapoolupdater::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("rolling-updates", "methods: 'cancel', 'get', 'insert', 'list', 'list-instance-updates', 'pause', 'resume' and 'rollback'", vec![ + ("cancel", + Some(r##"Cancels an update. The update must be PAUSED before it can be cancelled. This has no effect if the update is already CANCELLED."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapoolupdater1_beta1_cli/rolling-updates_cancel", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the update's target resides."##), + Some(true), + Some(false)), + + (Some(r##"rolling-update"##), + None, + Some(r##"The name of the update."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Returns information about an update."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapoolupdater1_beta1_cli/rolling-updates_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the update's target resides."##), + Some(true), + Some(false)), + + (Some(r##"rolling-update"##), + None, + Some(r##"The name of the update."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts and starts a new update."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapoolupdater1_beta1_cli/rolling-updates_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the update's target resides."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists recent updates for a given managed instance group, in reverse chronological order and paginated format."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapoolupdater1_beta1_cli/rolling-updates_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the update's target resides."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-instance-updates", + Some(r##"Lists the current status for each instance within a given update."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapoolupdater1_beta1_cli/rolling-updates_list-instance-updates", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the update's target resides."##), + Some(true), + Some(false)), + + (Some(r##"rolling-update"##), + None, + Some(r##"The name of the update."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("pause", + Some(r##"Pauses the update in state from ROLLING_FORWARD or ROLLING_BACK. Has no effect if invoked when the state of the update is PAUSED."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapoolupdater1_beta1_cli/rolling-updates_pause", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the update's target resides."##), + Some(true), + Some(false)), + + (Some(r##"rolling-update"##), + None, + Some(r##"The name of the update."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("resume", + Some(r##"Continues an update in PAUSED state. Has no effect if invoked when the state of the update is ROLLED_OUT."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapoolupdater1_beta1_cli/rolling-updates_resume", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the update's target resides."##), + Some(true), + Some(false)), + + (Some(r##"rolling-update"##), + None, + Some(r##"The name of the update."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("rollback", + Some(r##"Rolls back the update in state from ROLLING_FORWARD or PAUSED. Has no effect if invoked when the state of the update is ROLLED_BACK."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapoolupdater1_beta1_cli/rolling-updates_rollback", + vec![ + (Some(r##"project"##), + None, + Some(r##"The Google Developers Console project name."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The name of the zone in which the update's target resides."##), + Some(true), + Some(false)), + + (Some(r##"rolling-update"##), + None, + Some(r##"The name of the update."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("zone-operations", "methods: 'get'", vec![ + ("get", + Some(r##"Retrieves the specified zone-specific operation resource."##), + "Details at http://byron.github.io/google-apis-rs/google_replicapoolupdater1_beta1_cli/zone-operations_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Name of the zone scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"operation"##), + None, + Some(r##"Name of the operation resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("replicapoolupdater1-beta1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150326") + .about("The Google Compute Engine Instance Group Updater API provides services for updating groups of Compute Engine Instances.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_replicapoolupdater1_beta1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/replicapoolupdater1_beta1/Cargo.toml b/gen/replicapoolupdater1_beta1/Cargo.toml index fb953646d2..203e8a2c16 100644 --- a/gen/replicapoolupdater1_beta1/Cargo.toml +++ b/gen/replicapoolupdater1_beta1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-replicapoolupdater1_beta1" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with replicapoolupdater (protocol v1beta1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/replicapoolupdater1_beta1" @@ -15,9 +15,10 @@ keywords = ["replicapoolupdater", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/replicapoolupdater1_beta1/README.md b/gen/replicapoolupdater1_beta1/README.md index 7686bb7dfa..74d580001f 100644 --- a/gen/replicapoolupdater1_beta1/README.md +++ b/gen/replicapoolupdater1_beta1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-replicapoolupdater1_beta1` library allows access to all features of the *Google replicapoolupdater* service. -This documentation was generated from *replicapoolupdater* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *replicapoolupdater:v1beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *replicapoolupdater* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *replicapoolupdater:v1beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *replicapoolupdater* *v1_beta1* API can be found at the [official documentation site](https://cloud.google.com/compute/docs/instance-groups/manager/#applying_rolling_updates_using_the_updater_service). @@ -170,7 +170,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_replicapoolupdater1_beta1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_replicapoolupdater1_beta1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/replicapoolupdater1_beta1/src/cmn.rs b/gen/replicapoolupdater1_beta1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/replicapoolupdater1_beta1/src/cmn.rs +++ b/gen/replicapoolupdater1_beta1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/replicapoolupdater1_beta1/src/lib.rs b/gen/replicapoolupdater1_beta1/src/lib.rs index 1d9e3094f4..29adf99101 100644 --- a/gen/replicapoolupdater1_beta1/src/lib.rs +++ b/gen/replicapoolupdater1_beta1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *replicapoolupdater* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *replicapoolupdater:v1beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *replicapoolupdater* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *replicapoolupdater:v1beta1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *replicapoolupdater* *v1_beta1* API can be found at the //! [official documentation site](https://cloud.google.com/compute/docs/instance-groups/manager/#applying_rolling_updates_using_the_updater_service). @@ -171,7 +171,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -180,7 +180,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -196,6 +195,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -324,7 +324,7 @@ impl<'a, C, A> Replicapoolupdater<C, A> Replicapoolupdater { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -336,7 +336,7 @@ impl<'a, C, A> Replicapoolupdater<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1121,7 +1121,7 @@ impl<'a, C, A> RollingUpdatePauseCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1143,7 +1143,7 @@ impl<'a, C, A> RollingUpdatePauseCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1384,7 +1384,7 @@ impl<'a, C, A> RollingUpdateRollbackCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1406,7 +1406,7 @@ impl<'a, C, A> RollingUpdateRollbackCall<'a, C, A> where C: BorrowMut<hyper::Cli access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1647,7 +1647,7 @@ impl<'a, C, A> RollingUpdateGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1669,7 +1669,7 @@ impl<'a, C, A> RollingUpdateGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1910,7 +1910,7 @@ impl<'a, C, A> RollingUpdateResumeCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1932,7 +1932,7 @@ impl<'a, C, A> RollingUpdateResumeCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2191,7 +2191,7 @@ impl<'a, C, A> RollingUpdateListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2213,7 +2213,7 @@ impl<'a, C, A> RollingUpdateListCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2421,6 +2421,7 @@ impl<'a, C, A> RollingUpdateInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2477,11 +2478,20 @@ impl<'a, C, A> RollingUpdateInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2504,7 +2514,7 @@ impl<'a, C, A> RollingUpdateInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2762,7 +2772,7 @@ impl<'a, C, A> RollingUpdateListInstanceUpdateCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2784,7 +2794,7 @@ impl<'a, C, A> RollingUpdateListInstanceUpdateCall<'a, C, A> where C: BorrowMut< access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3046,7 +3056,7 @@ impl<'a, C, A> RollingUpdateCancelCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3068,7 +3078,7 @@ impl<'a, C, A> RollingUpdateCancelCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3309,7 +3319,7 @@ impl<'a, C, A> ZoneOperationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3331,7 +3341,7 @@ impl<'a, C, A> ZoneOperationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/reseller1_sandbox-cli/Cargo.toml b/gen/reseller1_sandbox-cli/Cargo.toml index 0aadbbd7d5..f4b659db49 100644 --- a/gen/reseller1_sandbox-cli/Cargo.toml +++ b/gen/reseller1_sandbox-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-reseller1_sandbox-cli" -version = "0.1.0+20141112" +version = "0.2.0+20141112" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with reseller (protocol v1sandbox)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/reseller1_sandbox-cli" @@ -17,15 +17,14 @@ keywords = ["reseller", "google", "cli"] name = "reseller1-sandbox" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-reseller1_sandbox] path = "../reseller1_sandbox" diff --git a/gen/reseller1_sandbox-cli/README.md b/gen/reseller1_sandbox-cli/README.md index a8f2b10074..6119d9acbf 100644 --- a/gen/reseller1_sandbox-cli/README.md +++ b/gen/reseller1_sandbox-cli/README.md @@ -10,34 +10,37 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *reseller* API can be found at the +[official documentation site](https://developers.google.com/google-apps/reseller/). + # Usage -This documentation was generated from the *reseller* API at revision *20141112*. The CLI is at version *0.1.0*. +This documentation was generated from the *reseller* API at revision *20141112*. The CLI is at version *0.2.0*. ```bash - reseller1-sandbox [options] customers get <customer-id> [-p <v>...] [-o <out>] - reseller1-sandbox [options] customers insert -r <kv>... [-p <v>...] [-o <out>] - reseller1-sandbox [options] customers patch <customer-id> -r <kv>... [-p <v>...] [-o <out>] - reseller1-sandbox [options] customers update <customer-id> -r <kv>... [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions activate <customer-id> <subscription-id> [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions change-plan <customer-id> <subscription-id> -r <kv>... [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions change-renewal-settings <customer-id> <subscription-id> -r <kv>... [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions change-seats <customer-id> <subscription-id> -r <kv>... [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions delete <customer-id> <subscription-id> <deletion-type> [-p <v>...] - reseller1-sandbox [options] subscriptions get <customer-id> <subscription-id> [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions insert <customer-id> -r <kv>... [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions list [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions start-paid-service <customer-id> <subscription-id> [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions suspend <customer-id> <subscription-id> [-p <v>...] [-o <out>] +reseller1-sandbox [options] + customers + get <customer-id> [-p <v>]... [-o <out>] + insert (-r <kv>)... [-p <v>]... [-o <out>] + patch <customer-id> (-r <kv>)... [-p <v>]... [-o <out>] + update <customer-id> (-r <kv>)... [-p <v>]... [-o <out>] + subscriptions + activate <customer-id> <subscription-id> [-p <v>]... [-o <out>] + change-plan <customer-id> <subscription-id> (-r <kv>)... [-p <v>]... [-o <out>] + change-renewal-settings <customer-id> <subscription-id> (-r <kv>)... [-p <v>]... [-o <out>] + change-seats <customer-id> <subscription-id> (-r <kv>)... [-p <v>]... [-o <out>] + delete <customer-id> <subscription-id> <deletion-type> [-p <v>]... + get <customer-id> <subscription-id> [-p <v>]... [-o <out>] + insert <customer-id> (-r <kv>)... [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + start-paid-service <customer-id> <subscription-id> [-p <v>]... [-o <out>] + suspend <customer-id> <subscription-id> [-p <v>]... [-o <out>] reseller1-sandbox --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/reseller1_sandbox-cli/mkdocs.yml b/gen/reseller1_sandbox-cli/mkdocs.yml index 8a16c05f51..4cd85bbdfe 100644 --- a/gen/reseller1_sandbox-cli/mkdocs.yml +++ b/gen/reseller1_sandbox-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: reseller v0.1.0+20141112 +site_name: reseller v0.2.0+20141112 site_url: http://byron.github.io/google-apis-rs/google-reseller1_sandbox-cli site_description: Write integrating applications with bcore diff --git a/gen/reseller1_sandbox-cli/src/cmn.rs b/gen/reseller1_sandbox-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/reseller1_sandbox-cli/src/cmn.rs +++ b/gen/reseller1_sandbox-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/reseller1_sandbox-cli/src/main.rs b/gen/reseller1_sandbox-cli/src/main.rs index 3c63f4f65b..f6d005192b 100644 --- a/gen/reseller1_sandbox-cli/src/main.rs +++ b/gen/reseller1_sandbox-cli/src/main.rs @@ -2,128 +2,105 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_reseller1_sandbox as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - reseller1-sandbox [options] customers get <customer-id> [-p <v>...] [-o <out>] - reseller1-sandbox [options] customers insert -r <kv>... [-p <v>...] [-o <out>] - reseller1-sandbox [options] customers patch <customer-id> -r <kv>... [-p <v>...] [-o <out>] - reseller1-sandbox [options] customers update <customer-id> -r <kv>... [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions activate <customer-id> <subscription-id> [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions change-plan <customer-id> <subscription-id> -r <kv>... [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions change-renewal-settings <customer-id> <subscription-id> -r <kv>... [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions change-seats <customer-id> <subscription-id> -r <kv>... [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions delete <customer-id> <subscription-id> <deletion-type> [-p <v>...] - reseller1-sandbox [options] subscriptions get <customer-id> <subscription-id> [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions insert <customer-id> -r <kv>... [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions list [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions start-paid-service <customer-id> <subscription-id> [-p <v>...] [-o <out>] - reseller1-sandbox [options] subscriptions suspend <customer-id> <subscription-id> [-p <v>...] [-o <out>] - reseller1-sandbox --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Reseller<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _customers_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.customers().get(&self.opt.arg_customer_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _customers_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.customers().get(opt.value_of("customer-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _customers_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _customers_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Customer::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -204,63 +181,68 @@ impl Engine { request.customer_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address-line1", "address-line2", "address-line3", "alternate-email", "contact-name", "country-code", "customer-domain", "customer-id", "kind", "locality", "organization-name", "phone-number", "postal-address", "postal-code", "region", "resource-ui-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.customers().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "customer-auth-token" => { call = call.customer_auth_token(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["customer-auth-token"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _customers_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _customers_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Customer::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -341,60 +323,65 @@ impl Engine { request.customer_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address-line1", "address-line2", "address-line3", "alternate-email", "contact-name", "country-code", "customer-domain", "customer-id", "kind", "locality", "organization-name", "phone-number", "postal-address", "postal-code", "region", "resource-ui-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.customers().patch(request, &self.opt.arg_customer_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.customers().patch(request, opt.value_of("customer-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _customers_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _customers_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Customer::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -475,106 +462,115 @@ impl Engine { request.customer_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address-line1", "address-line2", "address-line3", "alternate-email", "contact-name", "country-code", "customer-domain", "customer-id", "kind", "locality", "organization-name", "phone-number", "postal-address", "postal-code", "region", "resource-ui-url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.customers().update(request, &self.opt.arg_customer_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.customers().update(request, opt.value_of("customer-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _subscriptions_activate(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.subscriptions().activate(&self.opt.arg_customer_id, &self.opt.arg_subscription_id); - for parg in self.opt.arg_v.iter() { + fn _subscriptions_activate(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.subscriptions().activate(opt.value_of("customer-id").unwrap_or(""), opt.value_of("subscription-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _subscriptions_change_plan(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _subscriptions_change_plan(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ChangePlanRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -622,60 +618,65 @@ impl Engine { request.purchase_order_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind", "licensed-number-of-seats", "maximum-number-of-seats", "number-of-seats", "plan-name", "purchase-order-id", "seats"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.subscriptions().change_plan(request, &self.opt.arg_customer_id, &self.opt.arg_subscription_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.subscriptions().change_plan(request, opt.value_of("customer-id").unwrap_or(""), opt.value_of("subscription-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _subscriptions_change_renewal_settings(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _subscriptions_change_renewal_settings(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::RenewalSettings::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -697,60 +698,65 @@ impl Engine { request.renewal_type = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind", "renewal-type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.subscriptions().change_renewal_settings(request, &self.opt.arg_customer_id, &self.opt.arg_subscription_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.subscriptions().change_renewal_settings(request, opt.value_of("customer-id").unwrap_or(""), opt.value_of("subscription-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _subscriptions_change_seats(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _subscriptions_change_seats(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Seats::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -778,150 +784,158 @@ impl Engine { request.licensed_number_of_seats = Some(arg_from_str(value.unwrap_or("-0"), err, "licensed-number-of-seats", "integer")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["kind", "licensed-number-of-seats", "maximum-number-of-seats", "number-of-seats"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.subscriptions().change_seats(request, &self.opt.arg_customer_id, &self.opt.arg_subscription_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.subscriptions().change_seats(request, opt.value_of("customer-id").unwrap_or(""), opt.value_of("subscription-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _subscriptions_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.subscriptions().delete(&self.opt.arg_customer_id, &self.opt.arg_subscription_id, &self.opt.arg_deletion_type); - for parg in self.opt.arg_v.iter() { + fn _subscriptions_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.subscriptions().delete(opt.value_of("customer-id").unwrap_or(""), opt.value_of("subscription-id").unwrap_or(""), opt.value_of("deletion-type").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _subscriptions_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.subscriptions().get(&self.opt.arg_customer_id, &self.opt.arg_subscription_id); - for parg in self.opt.arg_v.iter() { + fn _subscriptions_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.subscriptions().get(opt.value_of("customer-id").unwrap_or(""), opt.value_of("subscription-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _subscriptions_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _subscriptions_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Subscription::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1066,61 +1080,66 @@ impl Engine { request.customer_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["billing-method", "commitment-interval", "creation-time", "customer-id", "end-time", "is-commitment-plan", "is-in-trial", "kind", "licensed-number-of-seats", "maximum-number-of-seats", "minimum-transferable-seats", "number-of-seats", "plan", "plan-name", "purchase-order-id", "renewal-settings", "renewal-type", "resource-ui-url", "seats", "sku-id", "start-time", "status", "subscription-id", "transfer-info", "transferability-expiration-time", "trial-end-time", "trial-settings"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.subscriptions().insert(request, &self.opt.arg_customer_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.subscriptions().insert(request, opt.value_of("customer-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "customer-auth-token" => { call = call.customer_auth_token(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["customer-auth-token"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _subscriptions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _subscriptions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.subscriptions().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1138,196 +1157,233 @@ impl Engine { "customer-auth-token" => { call = call.customer_auth_token(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["customer-auth-token", "page-token", "customer-id", "max-results", "customer-name-prefix"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _subscriptions_start_paid_service(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.subscriptions().start_paid_service(&self.opt.arg_customer_id, &self.opt.arg_subscription_id); - for parg in self.opt.arg_v.iter() { + fn _subscriptions_start_paid_service(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.subscriptions().start_paid_service(opt.value_of("customer-id").unwrap_or(""), opt.value_of("subscription-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _subscriptions_suspend(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.subscriptions().suspend(&self.opt.arg_customer_id, &self.opt.arg_subscription_id); - for parg in self.opt.arg_v.iter() { + fn _subscriptions_suspend(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.subscriptions().suspend(opt.value_of("customer-id").unwrap_or(""), opt.value_of("subscription-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_customers { - if self.opt.cmd_get { - call_result = self._customers_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._customers_insert(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._customers_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._customers_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("customers", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._customers_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._customers_insert(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._customers_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._customers_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("customers".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("subscriptions", Some(opt)) => { + match opt.subcommand() { + ("activate", Some(opt)) => { + call_result = self._subscriptions_activate(opt, dry_run, &mut err); + }, + ("change-plan", Some(opt)) => { + call_result = self._subscriptions_change_plan(opt, dry_run, &mut err); + }, + ("change-renewal-settings", Some(opt)) => { + call_result = self._subscriptions_change_renewal_settings(opt, dry_run, &mut err); + }, + ("change-seats", Some(opt)) => { + call_result = self._subscriptions_change_seats(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._subscriptions_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._subscriptions_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._subscriptions_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._subscriptions_list(opt, dry_run, &mut err); + }, + ("start-paid-service", Some(opt)) => { + call_result = self._subscriptions_start_paid_service(opt, dry_run, &mut err); + }, + ("suspend", Some(opt)) => { + call_result = self._subscriptions_suspend(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("subscriptions".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_subscriptions { - if self.opt.cmd_activate { - call_result = self._subscriptions_activate(dry_run, &mut err); - } else if self.opt.cmd_change_plan { - call_result = self._subscriptions_change_plan(dry_run, &mut err); - } else if self.opt.cmd_change_renewal_settings { - call_result = self._subscriptions_change_renewal_settings(dry_run, &mut err); - } else if self.opt.cmd_change_seats { - call_result = self._subscriptions_change_seats(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._subscriptions_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._subscriptions_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._subscriptions_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._subscriptions_list(dry_run, &mut err); - } else if self.opt.cmd_start_paid_service { - call_result = self._subscriptions_start_paid_service(dry_run, &mut err); - } else if self.opt.cmd_suspend { - call_result = self._subscriptions_suspend(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -1340,7 +1396,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1353,7 +1409,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1363,37 +1419,515 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Reseller::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("customers", "methods: 'get', 'insert', 'patch' and 'update'", vec![ + ("get", + Some(r##"Gets a customer resource if one exists and is owned by the reseller."##), + "Details at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/customers_get", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Id of the Customer"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a customer resource if one does not already exist."##), + "Details at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/customers_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update a customer resource if one it exists and is owned by the reseller. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/customers_patch", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Id of the Customer"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update a customer resource if one it exists and is owned by the reseller."##), + "Details at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/customers_update", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Id of the Customer"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("subscriptions", "methods: 'activate', 'change-plan', 'change-renewal-settings', 'change-seats', 'delete', 'get', 'insert', 'list', 'start-paid-service' and 'suspend'", vec![ + ("activate", + Some(r##"Activates a subscription previously suspended by the reseller"##), + "Details at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/subscriptions_activate", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Id of the Customer"##), + Some(true), + Some(false)), + + (Some(r##"subscription-id"##), + None, + Some(r##"Id of the subscription, which is unique for a customer"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("change-plan", + Some(r##"Changes the plan of a subscription"##), + "Details at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/subscriptions_change-plan", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Id of the Customer"##), + Some(true), + Some(false)), + + (Some(r##"subscription-id"##), + None, + Some(r##"Id of the subscription, which is unique for a customer"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("change-renewal-settings", + Some(r##"Changes the renewal settings of a subscription"##), + "Details at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/subscriptions_change-renewal-settings", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Id of the Customer"##), + Some(true), + Some(false)), + + (Some(r##"subscription-id"##), + None, + Some(r##"Id of the subscription, which is unique for a customer"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("change-seats", + Some(r##"Changes the seats configuration of a subscription"##), + "Details at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/subscriptions_change-seats", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Id of the Customer"##), + Some(true), + Some(false)), + + (Some(r##"subscription-id"##), + None, + Some(r##"Id of the subscription, which is unique for a customer"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Cancels/Downgrades a subscription."##), + "Details at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/subscriptions_delete", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Id of the Customer"##), + Some(true), + Some(false)), + + (Some(r##"subscription-id"##), + None, + Some(r##"Id of the subscription, which is unique for a customer"##), + Some(true), + Some(false)), + + (Some(r##"deletion-type"##), + None, + Some(r##"Whether the subscription is to be fully cancelled or downgraded"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Gets a subscription of the customer."##), + "Details at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/subscriptions_get", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Id of the Customer"##), + Some(true), + Some(false)), + + (Some(r##"subscription-id"##), + None, + Some(r##"Id of the subscription, which is unique for a customer"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates/Transfers a subscription for the customer."##), + "Details at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/subscriptions_insert", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Id of the Customer"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists subscriptions of a reseller, optionally filtered by a customer name prefix."##), + "Details at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/subscriptions_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("start-paid-service", + Some(r##"Starts paid service of a trial subscription"##), + "Details at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/subscriptions_start-paid-service", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Id of the Customer"##), + Some(true), + Some(false)), + + (Some(r##"subscription-id"##), + None, + Some(r##"Id of the subscription, which is unique for a customer"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("suspend", + Some(r##"Suspends an active subscription"##), + "Details at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli/subscriptions_suspend", + vec![ + (Some(r##"customer-id"##), + None, + Some(r##"Id of the Customer"##), + Some(true), + Some(false)), + + (Some(r##"subscription-id"##), + None, + Some(r##"Id of the subscription, which is unique for a customer"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("reseller1-sandbox") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20141112") + .about("Lets you create and manage your customers and their subscriptions.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_reseller1_sandbox_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/reseller1_sandbox/Cargo.toml b/gen/reseller1_sandbox/Cargo.toml index d8dd6a0470..5beaae620d 100644 --- a/gen/reseller1_sandbox/Cargo.toml +++ b/gen/reseller1_sandbox/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-reseller1_sandbox" -version = "0.1.6+20141112" +version = "0.1.7+20141112" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with reseller (protocol v1sandbox)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/reseller1_sandbox" @@ -15,9 +15,10 @@ keywords = ["reseller", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/reseller1_sandbox/README.md b/gen/reseller1_sandbox/README.md index 7c91461c1d..5b3aad5fff 100644 --- a/gen/reseller1_sandbox/README.md +++ b/gen/reseller1_sandbox/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-reseller1_sandbox` library allows access to all features of the *Google reseller* service. -This documentation was generated from *reseller* crate version *0.1.6+20141112*, where *20141112* is the exact revision of the *reseller:v1sandbox* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *reseller* crate version *0.1.7+20141112*, where *20141112* is the exact revision of the *reseller:v1sandbox* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *reseller* *v1_sandbox* API can be found at the [official documentation site](https://developers.google.com/google-apps/reseller/). @@ -173,7 +173,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_reseller1_sandbox/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_reseller1_sandbox/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/reseller1_sandbox/src/cmn.rs b/gen/reseller1_sandbox/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/reseller1_sandbox/src/cmn.rs +++ b/gen/reseller1_sandbox/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/reseller1_sandbox/src/lib.rs b/gen/reseller1_sandbox/src/lib.rs index d960b6e033..19d087af91 100644 --- a/gen/reseller1_sandbox/src/lib.rs +++ b/gen/reseller1_sandbox/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *reseller* crate version *0.1.6+20141112*, where *20141112* is the exact revision of the *reseller:v1sandbox* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *reseller* crate version *0.1.7+20141112*, where *20141112* is the exact revision of the *reseller:v1sandbox* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *reseller* *v1_sandbox* API can be found at the //! [official documentation site](https://developers.google.com/google-apps/reseller/). @@ -174,7 +174,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -183,7 +183,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -199,6 +198,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -324,7 +324,7 @@ impl<'a, C, A> Reseller<C, A> Reseller { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -336,7 +336,7 @@ impl<'a, C, A> Reseller<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1083,6 +1083,7 @@ impl<'a, C, A> CustomerUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Customer)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1138,11 +1139,20 @@ impl<'a, C, A> CustomerUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1165,7 +1175,7 @@ impl<'a, C, A> CustomerUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1347,6 +1357,7 @@ impl<'a, C, A> CustomerInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Customer)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1380,11 +1391,20 @@ impl<'a, C, A> CustomerInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1407,7 +1427,7 @@ impl<'a, C, A> CustomerInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1585,6 +1605,7 @@ impl<'a, C, A> CustomerPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Customer)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1640,11 +1661,20 @@ impl<'a, C, A> CustomerPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1667,7 +1697,7 @@ impl<'a, C, A> CustomerPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1896,7 +1926,7 @@ impl<'a, C, A> CustomerGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1918,7 +1948,7 @@ impl<'a, C, A> CustomerGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2089,6 +2119,7 @@ impl<'a, C, A> SubscriptionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Subscription)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2147,11 +2178,20 @@ impl<'a, C, A> SubscriptionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2174,7 +2214,7 @@ impl<'a, C, A> SubscriptionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2413,7 +2453,7 @@ impl<'a, C, A> SubscriptionDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2435,7 +2475,7 @@ impl<'a, C, A> SubscriptionDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2664,7 +2704,7 @@ impl<'a, C, A> SubscriptionGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2686,7 +2726,7 @@ impl<'a, C, A> SubscriptionGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2912,7 +2952,7 @@ impl<'a, C, A> SubscriptionListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2934,7 +2974,7 @@ impl<'a, C, A> SubscriptionListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3129,6 +3169,7 @@ impl<'a, C, A> SubscriptionChangeRenewalSettingCall<'a, C, A> where C: BorrowMut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Subscription)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3185,11 +3226,20 @@ impl<'a, C, A> SubscriptionChangeRenewalSettingCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3212,7 +3262,7 @@ impl<'a, C, A> SubscriptionChangeRenewalSettingCall<'a, C, A> where C: BorrowMut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3453,7 +3503,7 @@ impl<'a, C, A> SubscriptionStartPaidServiceCall<'a, C, A> where C: BorrowMut<hyp if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3475,7 +3525,7 @@ impl<'a, C, A> SubscriptionStartPaidServiceCall<'a, C, A> where C: BorrowMut<hyp access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3655,6 +3705,7 @@ impl<'a, C, A> SubscriptionChangeSeatCall<'a, C, A> where C: BorrowMut<hyper::Cl /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Subscription)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3711,11 +3762,20 @@ impl<'a, C, A> SubscriptionChangeSeatCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3738,7 +3798,7 @@ impl<'a, C, A> SubscriptionChangeSeatCall<'a, C, A> where C: BorrowMut<hyper::Cl request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3979,7 +4039,7 @@ impl<'a, C, A> SubscriptionSuspendCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4001,7 +4061,7 @@ impl<'a, C, A> SubscriptionSuspendCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4230,7 +4290,7 @@ impl<'a, C, A> SubscriptionActivateCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4252,7 +4312,7 @@ impl<'a, C, A> SubscriptionActivateCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4432,6 +4492,7 @@ impl<'a, C, A> SubscriptionChangePlanCall<'a, C, A> where C: BorrowMut<hyper::Cl /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Subscription)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4488,11 +4549,20 @@ impl<'a, C, A> SubscriptionChangePlanCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4515,7 +4585,7 @@ impl<'a, C, A> SubscriptionChangePlanCall<'a, C, A> where C: BorrowMut<hyper::Cl request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) diff --git a/gen/resourceviews1_beta2-cli/Cargo.toml b/gen/resourceviews1_beta2-cli/Cargo.toml index b3299511b4..a4093082b6 100644 --- a/gen/resourceviews1_beta2-cli/Cargo.toml +++ b/gen/resourceviews1_beta2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-resourceviews1_beta2-cli" -version = "0.1.0+20150302" +version = "0.2.0+20150302" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with resourceviews (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/resourceviews1_beta2-cli" @@ -17,15 +17,14 @@ keywords = ["resourceviews", "google", "cli"] name = "resourceviews1-beta2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-resourceviews1_beta2] path = "../resourceviews1_beta2" diff --git a/gen/resourceviews1_beta2-cli/README.md b/gen/resourceviews1_beta2-cli/README.md index c3e9f42ea4..c283896596 100644 --- a/gen/resourceviews1_beta2-cli/README.md +++ b/gen/resourceviews1_beta2-cli/README.md @@ -10,31 +10,34 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *resourceviews* API can be found at the +[official documentation site](https://developers.google.com/compute/). + # Usage -This documentation was generated from the *resourceviews* API at revision *20150302*. The CLI is at version *0.1.0*. +This documentation was generated from the *resourceviews* API at revision *20150302*. The CLI is at version *0.2.0*. ```bash - resourceviews1-beta2 [options] zone-operations get <project> <zone> <operation> [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-operations list <project> <zone> [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views add-resources <project> <zone> <resource-view> -r <kv>... [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views delete <project> <zone> <resource-view> [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views get <project> <zone> <resource-view> [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views get-service <project> <zone> <resource-view> [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views insert <project> <zone> -r <kv>... [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views list <project> <zone> [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views list-resources <project> <zone> <resource-view> [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views remove-resources <project> <zone> <resource-view> -r <kv>... [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views set-service <project> <zone> <resource-view> -r <kv>... [-p <v>...] [-o <out>] +resourceviews1-beta2 [options] + zone-operations + get <project> <zone> <operation> [-p <v>]... [-o <out>] + list <project> <zone> [-p <v>]... [-o <out>] + zone-views + add-resources <project> <zone> <resource-view> (-r <kv>)... [-p <v>]... [-o <out>] + delete <project> <zone> <resource-view> [-p <v>]... [-o <out>] + get <project> <zone> <resource-view> [-p <v>]... [-o <out>] + get-service <project> <zone> <resource-view> [-p <v>]... [-o <out>] + insert <project> <zone> (-r <kv>)... [-p <v>]... [-o <out>] + list <project> <zone> [-p <v>]... [-o <out>] + list-resources <project> <zone> <resource-view> [-p <v>]... [-o <out>] + remove-resources <project> <zone> <resource-view> (-r <kv>)... [-p <v>]... [-o <out>] + set-service <project> <zone> <resource-view> (-r <kv>)... [-p <v>]... [-o <out>] resourceviews1-beta2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_resourceviews1_beta2_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/resourceviews1_beta2-cli/mkdocs.yml b/gen/resourceviews1_beta2-cli/mkdocs.yml index fe57850c86..a6c4e75d51 100644 --- a/gen/resourceviews1_beta2-cli/mkdocs.yml +++ b/gen/resourceviews1_beta2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: resourceviews v0.1.0+20150302 +site_name: resourceviews v0.2.0+20150302 site_url: http://byron.github.io/google-apis-rs/google-resourceviews1_beta2-cli site_description: Write integrating applications with bcore diff --git a/gen/resourceviews1_beta2-cli/src/cmn.rs b/gen/resourceviews1_beta2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/resourceviews1_beta2-cli/src/cmn.rs +++ b/gen/resourceviews1_beta2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/resourceviews1_beta2-cli/src/main.rs b/gen/resourceviews1_beta2-cli/src/main.rs index e61e22f959..73d176e4d7 100644 --- a/gen/resourceviews1_beta2-cli/src/main.rs +++ b/gen/resourceviews1_beta2-cli/src/main.rs @@ -2,123 +2,103 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_resourceviews1_beta2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - resourceviews1-beta2 [options] zone-operations get <project> <zone> <operation> [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-operations list <project> <zone> [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views add-resources <project> <zone> <resource-view> -r <kv>... [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views delete <project> <zone> <resource-view> [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views get <project> <zone> <resource-view> [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views get-service <project> <zone> <resource-view> [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views insert <project> <zone> -r <kv>... [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views list <project> <zone> [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views list-resources <project> <zone> <resource-view> [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views remove-resources <project> <zone> <resource-view> -r <kv>... [-p <v>...] [-o <out>] - resourceviews1-beta2 [options] zone-views set-service <project> <zone> <resource-view> -r <kv>... [-p <v>...] [-o <out>] - resourceviews1-beta2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_resourceviews1_beta2_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Resourceviews<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _zone_operations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.zone_operations().get(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_operation); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _zone_operations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_operations().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("operation").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_operations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.zone_operations().list(&self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + fn _zone_operations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_operations().list(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -130,52 +110,56 @@ impl Engine { "filter" => { call = call.filter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["filter", "page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_views_add_resources(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _zone_views_add_resources(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ZoneViewsAddResourcesRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -197,201 +181,218 @@ impl Engine { request.resources.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["resources"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.zone_views().add_resources(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_resource_view); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.zone_views().add_resources(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("resource-view").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_views_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.zone_views().delete(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_resource_view); - for parg in self.opt.arg_v.iter() { + fn _zone_views_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_views().delete(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("resource-view").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_views_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.zone_views().get(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_resource_view); - for parg in self.opt.arg_v.iter() { + fn _zone_views_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_views().get(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("resource-view").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_views_get_service(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.zone_views().get_service(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_resource_view); - for parg in self.opt.arg_v.iter() { + fn _zone_views_get_service(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_views().get_service(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("resource-view").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "resource-name" => { call = call.resource_name(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["resource-name"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_views_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _zone_views_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ResourceView::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -440,58 +441,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["creation-timestamp", "description", "fingerprint", "id", "kind", "name", "network", "resources", "self-link", "size"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.zone_views().insert(request, &self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.zone_views().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_views_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.zone_views().list(&self.opt.arg_project, &self.opt.arg_zone); - for parg in self.opt.arg_v.iter() { + fn _zone_views_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_views().list(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -500,50 +506,54 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_views_list_resources(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.zone_views().list_resources(&self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_resource_view); - for parg in self.opt.arg_v.iter() { + fn _zone_views_list_resources(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.zone_views().list_resources(opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("resource-view").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "service-name" => { @@ -561,52 +571,56 @@ impl Engine { "format" => { call = call.format(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "service-name", "list-state", "max-results", "format"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_views_remove_resources(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _zone_views_remove_resources(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ZoneViewsRemoveResourcesRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -628,60 +642,65 @@ impl Engine { request.resources.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["resources"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.zone_views().remove_resources(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_resource_view); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.zone_views().remove_resources(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("resource-view").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _zone_views_set_service(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _zone_views_set_service(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ZoneViewsSetServiceRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -703,106 +722,133 @@ impl Engine { request.fingerprint = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["fingerprint", "resource-name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.zone_views().set_service(request, &self.opt.arg_project, &self.opt.arg_zone, &self.opt.arg_resource_view); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.zone_views().set_service(request, opt.value_of("project").unwrap_or(""), opt.value_of("zone").unwrap_or(""), opt.value_of("resource-view").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_zone_operations { - if self.opt.cmd_get { - call_result = self._zone_operations_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._zone_operations_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("zone-operations", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._zone_operations_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._zone_operations_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("zone-operations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("zone-views", Some(opt)) => { + match opt.subcommand() { + ("add-resources", Some(opt)) => { + call_result = self._zone_views_add_resources(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._zone_views_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._zone_views_get(opt, dry_run, &mut err); + }, + ("get-service", Some(opt)) => { + call_result = self._zone_views_get_service(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._zone_views_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._zone_views_list(opt, dry_run, &mut err); + }, + ("list-resources", Some(opt)) => { + call_result = self._zone_views_list_resources(opt, dry_run, &mut err); + }, + ("remove-resources", Some(opt)) => { + call_result = self._zone_views_remove_resources(opt, dry_run, &mut err); + }, + ("set-service", Some(opt)) => { + call_result = self._zone_views_set_service(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("zone-views".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_zone_views { - if self.opt.cmd_add_resources { - call_result = self._zone_views_add_resources(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._zone_views_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._zone_views_get(dry_run, &mut err); - } else if self.opt.cmd_get_service { - call_result = self._zone_views_get_service(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._zone_views_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._zone_views_list(dry_run, &mut err); - } else if self.opt.cmd_list_resources { - call_result = self._zone_views_list_resources(dry_run, &mut err); - } else if self.opt.cmd_remove_resources { - call_result = self._zone_views_remove_resources(dry_run, &mut err); - } else if self.opt.cmd_set_service { - call_result = self._zone_views_set_service(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -815,7 +861,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -828,7 +874,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -838,37 +884,509 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Resourceviews::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("zone-operations", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Retrieves the specified zone-specific operation resource."##), + "Details at http://byron.github.io/google-apis-rs/google_resourceviews1_beta2_cli/zone-operations_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Name of the zone scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"operation"##), + None, + Some(r##"Name of the operation resource to return."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves the list of operation resources contained within the specified zone."##), + "Details at http://byron.github.io/google-apis-rs/google_resourceviews1_beta2_cli/zone-operations_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Name of the project scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"Name of the zone scoping this request."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("zone-views", "methods: 'add-resources', 'delete', 'get', 'get-service', 'insert', 'list', 'list-resources', 'remove-resources' and 'set-service'", vec![ + ("add-resources", + Some(r##"Add resources to the view."##), + "Details at http://byron.github.io/google-apis-rs/google_resourceviews1_beta2_cli/zone-views_add-resources", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The zone name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"resource-view"##), + None, + Some(r##"The name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Delete a resource view."##), + "Details at http://byron.github.io/google-apis-rs/google_resourceviews1_beta2_cli/zone-views_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The zone name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"resource-view"##), + None, + Some(r##"The name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Get the information of a zonal resource view."##), + "Details at http://byron.github.io/google-apis-rs/google_resourceviews1_beta2_cli/zone-views_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The zone name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"resource-view"##), + None, + Some(r##"The name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-service", + Some(r##"Get the service information of a resource view or a resource."##), + "Details at http://byron.github.io/google-apis-rs/google_resourceviews1_beta2_cli/zone-views_get-service", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The zone name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"resource-view"##), + None, + Some(r##"The name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Create a resource view."##), + "Details at http://byron.github.io/google-apis-rs/google_resourceviews1_beta2_cli/zone-views_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The zone name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List resource views."##), + "Details at http://byron.github.io/google-apis-rs/google_resourceviews1_beta2_cli/zone-views_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The zone name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list-resources", + Some(r##"List the resources of the resource view."##), + "Details at http://byron.github.io/google-apis-rs/google_resourceviews1_beta2_cli/zone-views_list-resources", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The zone name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"resource-view"##), + None, + Some(r##"The name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("remove-resources", + Some(r##"Remove resources from the view."##), + "Details at http://byron.github.io/google-apis-rs/google_resourceviews1_beta2_cli/zone-views_remove-resources", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The zone name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"resource-view"##), + None, + Some(r##"The name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("set-service", + Some(r##"Update the service information of a resource view or a resource."##), + "Details at http://byron.github.io/google-apis-rs/google_resourceviews1_beta2_cli/zone-views_set-service", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"zone"##), + None, + Some(r##"The zone name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"resource-view"##), + None, + Some(r##"The name of the resource view."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("resourceviews1-beta2") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150302") + .about("The Resource View API allows users to create and manage logical sets of Google Compute Engine instances.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_resourceviews1_beta2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/resourceviews1_beta2/Cargo.toml b/gen/resourceviews1_beta2/Cargo.toml index a4daa9d97b..bb429d7d54 100644 --- a/gen/resourceviews1_beta2/Cargo.toml +++ b/gen/resourceviews1_beta2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-resourceviews1_beta2" -version = "0.1.6+20150302" +version = "0.1.7+20150302" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with resourceviews (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/resourceviews1_beta2" @@ -15,9 +15,10 @@ keywords = ["resourceviews", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/resourceviews1_beta2/README.md b/gen/resourceviews1_beta2/README.md index 39de051bc3..41d809b1d5 100644 --- a/gen/resourceviews1_beta2/README.md +++ b/gen/resourceviews1_beta2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-resourceviews1_beta2` library allows access to all features of the *Google resourceviews* service. -This documentation was generated from *resourceviews* crate version *0.1.6+20150302*, where *20150302* is the exact revision of the *resourceviews:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *resourceviews* crate version *0.1.7+20150302*, where *20150302* is the exact revision of the *resourceviews:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *resourceviews* *v1_beta2* API can be found at the [official documentation site](https://developers.google.com/compute/). @@ -170,7 +170,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_resourceviews1_beta2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_resourceviews1_beta2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/resourceviews1_beta2/src/cmn.rs b/gen/resourceviews1_beta2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/resourceviews1_beta2/src/cmn.rs +++ b/gen/resourceviews1_beta2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/resourceviews1_beta2/src/lib.rs b/gen/resourceviews1_beta2/src/lib.rs index 14c99fc714..2c79b93f08 100644 --- a/gen/resourceviews1_beta2/src/lib.rs +++ b/gen/resourceviews1_beta2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *resourceviews* crate version *0.1.6+20150302*, where *20150302* is the exact revision of the *resourceviews:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *resourceviews* crate version *0.1.7+20150302*, where *20150302* is the exact revision of the *resourceviews:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *resourceviews* *v1_beta2* API can be found at the //! [official documentation site](https://developers.google.com/compute/). @@ -171,7 +171,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -180,7 +180,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -196,6 +195,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -334,7 +334,7 @@ impl<'a, C, A> Resourceviews<C, A> Resourceviews { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -346,7 +346,7 @@ impl<'a, C, A> Resourceviews<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1141,6 +1141,7 @@ impl<'a, C, A> ZoneViewRemoveResourceCall<'a, C, A> where C: BorrowMut<hyper::Cl /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1198,11 +1199,20 @@ impl<'a, C, A> ZoneViewRemoveResourceCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1225,7 +1235,7 @@ impl<'a, C, A> ZoneViewRemoveResourceCall<'a, C, A> where C: BorrowMut<hyper::Cl request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1428,6 +1438,7 @@ impl<'a, C, A> ZoneViewAddResourceCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1485,11 +1496,20 @@ impl<'a, C, A> ZoneViewAddResourceCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1512,7 +1532,7 @@ impl<'a, C, A> ZoneViewAddResourceCall<'a, C, A> where C: BorrowMut<hyper::Clien request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1790,7 +1810,7 @@ impl<'a, C, A> ZoneViewListResourceCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1812,7 +1832,7 @@ impl<'a, C, A> ZoneViewListResourceCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2088,7 +2108,7 @@ impl<'a, C, A> ZoneViewGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2110,7 +2130,7 @@ impl<'a, C, A> ZoneViewGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2359,7 +2379,7 @@ impl<'a, C, A> ZoneViewListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2381,7 +2401,7 @@ impl<'a, C, A> ZoneViewListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2575,6 +2595,7 @@ impl<'a, C, A> ZoneViewInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2631,11 +2652,20 @@ impl<'a, C, A> ZoneViewInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2658,7 +2688,7 @@ impl<'a, C, A> ZoneViewInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2901,7 +2931,7 @@ impl<'a, C, A> ZoneViewDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2923,7 +2953,7 @@ impl<'a, C, A> ZoneViewDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3114,6 +3144,7 @@ impl<'a, C, A> ZoneViewSetServiceCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3171,11 +3202,20 @@ impl<'a, C, A> ZoneViewSetServiceCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3198,7 +3238,7 @@ impl<'a, C, A> ZoneViewSetServiceCall<'a, C, A> where C: BorrowMut<hyper::Client request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3456,7 +3496,7 @@ impl<'a, C, A> ZoneViewGetServiceCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3478,7 +3518,7 @@ impl<'a, C, A> ZoneViewGetServiceCall<'a, C, A> where C: BorrowMut<hyper::Client access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3726,7 +3766,7 @@ impl<'a, C, A> ZoneOperationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3748,7 +3788,7 @@ impl<'a, C, A> ZoneOperationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4002,7 +4042,7 @@ impl<'a, C, A> ZoneOperationListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4024,7 +4064,7 @@ impl<'a, C, A> ZoneOperationListCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/siteverification1-cli/Cargo.toml b/gen/siteverification1-cli/Cargo.toml index fd219cdeb0..119c64e7ff 100644 --- a/gen/siteverification1-cli/Cargo.toml +++ b/gen/siteverification1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-siteverification1-cli" -version = "0.1.0+20131007" +version = "0.2.0+20131007" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with siteVerification (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/siteverification1-cli" @@ -17,15 +17,14 @@ keywords = ["siteVerification", "google", "cli"] name = "siteverification1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-siteverification1] path = "../siteverification1" diff --git a/gen/siteverification1-cli/README.md b/gen/siteverification1-cli/README.md index 5784f9d867..659182ca1b 100644 --- a/gen/siteverification1-cli/README.md +++ b/gen/siteverification1-cli/README.md @@ -10,27 +10,29 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *siteVerification* API can be found at the +[official documentation site](https://developers.google.com/site-verification/). + # Usage -This documentation was generated from the *siteVerification* API at revision *20131007*. The CLI is at version *0.1.0*. +This documentation was generated from the *siteVerification* API at revision *20131007*. The CLI is at version *0.2.0*. ```bash - siteverification1 [options] web-resource delete <id> [-p <v>...] - siteverification1 [options] web-resource get <id> [-p <v>...] [-o <out>] - siteverification1 [options] web-resource get-token -r <kv>... [-p <v>...] [-o <out>] - siteverification1 [options] web-resource insert <verification-method> -r <kv>... [-p <v>...] [-o <out>] - siteverification1 [options] web-resource list [-p <v>...] [-o <out>] - siteverification1 [options] web-resource patch <id> -r <kv>... [-p <v>...] [-o <out>] - siteverification1 [options] web-resource update <id> -r <kv>... [-p <v>...] [-o <out>] +siteverification1 [options] + web-resource + delete <id> [-p <v>]... + get <id> [-p <v>]... [-o <out>] + get-token (-r <kv>)... [-p <v>]... [-o <out>] + insert <verification-method> (-r <kv>)... [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + patch <id> (-r <kv>)... [-p <v>]... [-o <out>] + update <id> (-r <kv>)... [-p <v>]... [-o <out>] siteverification1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_siteverification1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/siteverification1-cli/mkdocs.yml b/gen/siteverification1-cli/mkdocs.yml index 9175061b57..e83ef156f0 100644 --- a/gen/siteverification1-cli/mkdocs.yml +++ b/gen/siteverification1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: siteVerification v0.1.0+20131007 +site_name: siteVerification v0.2.0+20131007 site_url: http://byron.github.io/google-apis-rs/google-siteverification1-cli site_description: Write integrating applications with bcore diff --git a/gen/siteverification1-cli/src/cmn.rs b/gen/siteverification1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/siteverification1-cli/src/cmn.rs +++ b/gen/siteverification1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/siteverification1-cli/src/main.rs b/gen/siteverification1-cli/src/main.rs index 88e9e6712e..fb9080f098 100644 --- a/gen/siteverification1-cli/src/main.rs +++ b/gen/siteverification1-cli/src/main.rs @@ -2,165 +2,148 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_siteverification1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - siteverification1 [options] web-resource delete <id> [-p <v>...] - siteverification1 [options] web-resource get <id> [-p <v>...] [-o <out>] - siteverification1 [options] web-resource get-token -r <kv>... [-p <v>...] [-o <out>] - siteverification1 [options] web-resource insert <verification-method> -r <kv>... [-p <v>...] [-o <out>] - siteverification1 [options] web-resource list [-p <v>...] [-o <out>] - siteverification1 [options] web-resource patch <id> -r <kv>... [-p <v>...] [-o <out>] - siteverification1 [options] web-resource update <id> -r <kv>... [-p <v>...] [-o <out>] - siteverification1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_siteverification1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::SiteVerification<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _web_resource_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.web_resource().delete(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _web_resource_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.web_resource().delete(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _web_resource_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.web_resource().get(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _web_resource_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.web_resource().get(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _web_resource_get_token(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _web_resource_get_token(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SiteVerificationWebResourceGettokenRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -193,60 +176,65 @@ impl Engine { request.site.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["identifier", "site", "type", "verification-method"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.web_resource().get_token(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _web_resource_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _web_resource_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SiteVerificationWebResourceResource::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -285,106 +273,115 @@ impl Engine { request.site.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "identifier", "owners", "site", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.web_resource().insert(request, &self.opt.arg_verification_method); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.web_resource().insert(request, opt.value_of("verification-method").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _web_resource_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _web_resource_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.web_resource().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _web_resource_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _web_resource_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SiteVerificationWebResourceResource::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -423,60 +420,65 @@ impl Engine { request.site.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "identifier", "owners", "site", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.web_resource().patch(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.web_resource().patch(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _web_resource_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _web_resource_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SiteVerificationWebResourceResource::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -515,93 +517,113 @@ impl Engine { request.site.as_mut().unwrap().type_ = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["id", "identifier", "owners", "site", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.web_resource().update(request, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.web_resource().update(request, opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_web_resource { - if self.opt.cmd_delete { - call_result = self._web_resource_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._web_resource_get(dry_run, &mut err); - } else if self.opt.cmd_get_token { - call_result = self._web_resource_get_token(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._web_resource_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._web_resource_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._web_resource_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._web_resource_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("web-resource", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._web_resource_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._web_resource_get(opt, dry_run, &mut err); + }, + ("get-token", Some(opt)) => { + call_result = self._web_resource_get_token(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._web_resource_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._web_resource_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._web_resource_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._web_resource_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("web-resource".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -614,7 +636,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -627,7 +649,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -637,37 +659,286 @@ impl Engine { let engine = Engine { opt: opt, hub: api::SiteVerification::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("web-resource", "methods: 'delete', 'get', 'get-token', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Relinquish ownership of a website or domain."##), + "Details at http://byron.github.io/google-apis-rs/google_siteverification1_cli/web-resource_delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The id of a verified site or domain."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Get the most current data for a website or domain."##), + "Details at http://byron.github.io/google-apis-rs/google_siteverification1_cli/web-resource_get", + vec![ + (Some(r##"id"##), + None, + Some(r##"The id of a verified site or domain."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-token", + Some(r##"Get a verification token for placing on a website or domain."##), + "Details at http://byron.github.io/google-apis-rs/google_siteverification1_cli/web-resource_get-token", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Attempt verification of a website or domain."##), + "Details at http://byron.github.io/google-apis-rs/google_siteverification1_cli/web-resource_insert", + vec![ + (Some(r##"verification-method"##), + None, + Some(r##"The method to use for verifying a site or domain."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Get the list of your verified websites and domains."##), + "Details at http://byron.github.io/google-apis-rs/google_siteverification1_cli/web-resource_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Modify the list of owners for your website or domain. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_siteverification1_cli/web-resource_patch", + vec![ + (Some(r##"id"##), + None, + Some(r##"The id of a verified site or domain."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Modify the list of owners for your website or domain."##), + "Details at http://byron.github.io/google-apis-rs/google_siteverification1_cli/web-resource_update", + vec![ + (Some(r##"id"##), + None, + Some(r##"The id of a verified site or domain."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("siteverification1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20131007") + .about("Lets you programatically verify ownership of websites or domains with Google.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_siteverification1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/siteverification1/Cargo.toml b/gen/siteverification1/Cargo.toml index 633b260513..f680c9fbdb 100644 --- a/gen/siteverification1/Cargo.toml +++ b/gen/siteverification1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-siteverification1" -version = "0.1.6+20131007" +version = "0.1.7+20131007" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with siteVerification (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/siteverification1" @@ -15,9 +15,10 @@ keywords = ["siteVerification", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/siteverification1/README.md b/gen/siteverification1/README.md index 760db29b23..aec75dda1d 100644 --- a/gen/siteverification1/README.md +++ b/gen/siteverification1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-siteverification1` library allows access to all features of the *Google siteVerification* service. -This documentation was generated from *siteVerification* crate version *0.1.6+20131007*, where *20131007* is the exact revision of the *siteVerification:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *siteVerification* crate version *0.1.7+20131007*, where *20131007* is the exact revision of the *siteVerification:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *siteVerification* *v1* API can be found at the [official documentation site](https://developers.google.com/site-verification/). @@ -166,7 +166,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_siteverification1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_siteverification1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/siteverification1/src/cmn.rs b/gen/siteverification1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/siteverification1/src/cmn.rs +++ b/gen/siteverification1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/siteverification1/src/lib.rs b/gen/siteverification1/src/lib.rs index 275c7b6098..eace4a87e2 100644 --- a/gen/siteverification1/src/lib.rs +++ b/gen/siteverification1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *siteVerification* crate version *0.1.6+20131007*, where *20131007* is the exact revision of the *siteVerification:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *siteVerification* crate version *0.1.7+20131007*, where *20131007* is the exact revision of the *siteVerification:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *siteVerification* *v1* API can be found at the //! [official documentation site](https://developers.google.com/site-verification/). @@ -167,7 +167,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -176,7 +176,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -192,6 +191,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -318,7 +318,7 @@ impl<'a, C, A> SiteVerification<C, A> SiteVerification { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -327,7 +327,7 @@ impl<'a, C, A> SiteVerification<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -734,7 +734,7 @@ impl<'a, C, A> WebResourceGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -756,7 +756,7 @@ impl<'a, C, A> WebResourceGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -925,6 +925,7 @@ impl<'a, C, A> WebResourcePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SiteVerificationWebResourceResource)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -980,11 +981,20 @@ impl<'a, C, A> WebResourcePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1007,7 +1017,7 @@ impl<'a, C, A> WebResourcePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1210,7 +1220,7 @@ impl<'a, C, A> WebResourceListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1232,7 +1242,7 @@ impl<'a, C, A> WebResourceListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1438,7 +1448,7 @@ impl<'a, C, A> WebResourceDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1460,7 +1470,7 @@ impl<'a, C, A> WebResourceDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client> access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1618,6 +1628,7 @@ impl<'a, C, A> WebResourceGetTokenCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SiteVerificationWebResourceGettokenResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1648,11 +1659,20 @@ impl<'a, C, A> WebResourceGetTokenCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1675,7 +1695,7 @@ impl<'a, C, A> WebResourceGetTokenCall<'a, C, A> where C: BorrowMut<hyper::Clien request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1846,6 +1866,7 @@ impl<'a, C, A> WebResourceUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client> /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SiteVerificationWebResourceResource)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1901,11 +1922,20 @@ impl<'a, C, A> WebResourceUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1928,7 +1958,7 @@ impl<'a, C, A> WebResourceUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client> request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2109,6 +2139,7 @@ impl<'a, C, A> WebResourceInsertCall<'a, C, A> where C: BorrowMut<hyper::Client> /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SiteVerificationWebResourceResource)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2140,11 +2171,20 @@ impl<'a, C, A> WebResourceInsertCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2167,7 +2207,7 @@ impl<'a, C, A> WebResourceInsertCall<'a, C, A> where C: BorrowMut<hyper::Client> request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) diff --git a/gen/spectrum1_explorer-cli/Cargo.toml b/gen/spectrum1_explorer-cli/Cargo.toml index 3cd5c28a05..1843a498bf 100644 --- a/gen/spectrum1_explorer-cli/Cargo.toml +++ b/gen/spectrum1_explorer-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-spectrum1_explorer-cli" -version = "0.1.0+20150112" +version = "0.2.0+20150112" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with spectrum (protocol v1explorer)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/spectrum1_explorer-cli" @@ -17,15 +17,14 @@ keywords = ["spectrum", "google", "cli"] name = "spectrum1-explorer" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-spectrum1_explorer] path = "../spectrum1_explorer" diff --git a/gen/spectrum1_explorer-cli/README.md b/gen/spectrum1_explorer-cli/README.md index 4b05f938fb..0ef7c6ccce 100644 --- a/gen/spectrum1_explorer-cli/README.md +++ b/gen/spectrum1_explorer-cli/README.md @@ -10,22 +10,24 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *spectrum* API can be found at the +[official documentation site](http://developers.google.com/spectrum). + # Usage -This documentation was generated from the *spectrum* API at revision *20150112*. The CLI is at version *0.1.0*. +This documentation was generated from the *spectrum* API at revision *20150112*. The CLI is at version *0.2.0*. ```bash - spectrum1-explorer [options] paws get-spectrum -r <kv>... [-p <v>...] [-o <out>] - spectrum1-explorer [options] paws get-spectrum-batch -r <kv>... [-p <v>...] [-o <out>] - spectrum1-explorer [options] paws init -r <kv>... [-p <v>...] [-o <out>] - spectrum1-explorer [options] paws notify-spectrum-use -r <kv>... [-p <v>...] [-o <out>] - spectrum1-explorer [options] paws register -r <kv>... [-p <v>...] [-o <out>] - spectrum1-explorer [options] paws verify-device -r <kv>... [-p <v>...] [-o <out>] +spectrum1-explorer [options] + paws + get-spectrum (-r <kv>)... [-p <v>]... [-o <out>] + get-spectrum-batch (-r <kv>)... [-p <v>]... [-o <out>] + init (-r <kv>)... [-p <v>]... [-o <out>] + notify-spectrum-use (-r <kv>)... [-p <v>]... [-o <out>] + register (-r <kv>)... [-p <v>]... [-o <out>] + verify-device (-r <kv>)... [-p <v>]... [-o <out>] spectrum1-explorer --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_spectrum1_explorer_cli/index.html - Configuration: --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/spectrum1_explorer-cli/mkdocs.yml b/gen/spectrum1_explorer-cli/mkdocs.yml index d066650ba1..8ebb2ef60d 100644 --- a/gen/spectrum1_explorer-cli/mkdocs.yml +++ b/gen/spectrum1_explorer-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: spectrum v0.1.0+20150112 +site_name: spectrum v0.2.0+20150112 site_url: http://byron.github.io/google-apis-rs/google-spectrum1_explorer-cli site_description: Write integrating applications with bcore diff --git a/gen/spectrum1_explorer-cli/src/cmn.rs b/gen/spectrum1_explorer-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/spectrum1_explorer-cli/src/cmn.rs +++ b/gen/spectrum1_explorer-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/spectrum1_explorer-cli/src/main.rs b/gen/spectrum1_explorer-cli/src/main.rs index 5cd26f841d..2ccfee6443 100644 --- a/gen/spectrum1_explorer-cli/src/main.rs +++ b/gen/spectrum1_explorer-cli/src/main.rs @@ -2,70 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_spectrum1_explorer as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - spectrum1-explorer [options] paws get-spectrum -r <kv>... [-p <v>...] [-o <out>] - spectrum1-explorer [options] paws get-spectrum-batch -r <kv>... [-p <v>...] [-o <out>] - spectrum1-explorer [options] paws init -r <kv>... [-p <v>...] [-o <out>] - spectrum1-explorer [options] paws notify-spectrum-use -r <kv>... [-p <v>...] [-o <out>] - spectrum1-explorer [options] paws register -r <kv>... [-p <v>...] [-o <out>] - spectrum1-explorer [options] paws verify-device -r <kv>... [-p <v>...] [-o <out>] - spectrum1-explorer --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_spectrum1_explorer_cli/index.html - -Configuration: - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Spectrum<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _paws_get_spectrum(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _paws_get_spectrum(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PawsGetSpectrumRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -409,57 +394,62 @@ impl Engine { request.type_ = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["adr", "antenna", "center", "code", "confidence", "country", "device-desc", "email", "etsi-en-device-category", "etsi-en-device-emissions-class", "etsi-en-device-type", "etsi-en-technology-id", "fcc-id", "fcc-tvbd-device-type", "fn", "height", "height-type", "height-uncertainty", "latitude", "locality", "location", "longitude", "manufacturer-id", "master-device-desc", "model-id", "operator", "org", "orientation", "owner", "pobox", "point", "region", "request-type", "ruleset-ids", "semi-major-axis", "semi-minor-axis", "serial-number", "street", "tel", "text", "type", "uri", "version"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.paws().get_spectrum(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _paws_get_spectrum_batch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _paws_get_spectrum_batch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PawsGetSpectrumBatchRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -759,57 +749,62 @@ impl Engine { request.type_ = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["adr", "antenna", "code", "country", "device-desc", "email", "etsi-en-device-category", "etsi-en-device-emissions-class", "etsi-en-device-type", "etsi-en-technology-id", "fcc-id", "fcc-tvbd-device-type", "fn", "height", "height-type", "height-uncertainty", "locality", "manufacturer-id", "master-device-desc", "model-id", "operator", "org", "owner", "pobox", "region", "request-type", "ruleset-ids", "serial-number", "street", "tel", "text", "type", "uri", "version"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.paws().get_spectrum_batch(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _paws_init(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _paws_init(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PawsInitRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -926,57 +921,62 @@ impl Engine { request.version = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["center", "confidence", "device-desc", "etsi-en-device-category", "etsi-en-device-emissions-class", "etsi-en-device-type", "etsi-en-technology-id", "fcc-id", "fcc-tvbd-device-type", "latitude", "location", "longitude", "manufacturer-id", "model-id", "orientation", "point", "ruleset-ids", "semi-major-axis", "semi-minor-axis", "serial-number", "type", "version"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.paws().init(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _paws_notify_spectrum_use(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _paws_notify_spectrum_use(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PawsNotifySpectrumUseRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1093,57 +1093,62 @@ impl Engine { request.version = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["center", "confidence", "device-desc", "etsi-en-device-category", "etsi-en-device-emissions-class", "etsi-en-device-type", "etsi-en-technology-id", "fcc-id", "fcc-tvbd-device-type", "latitude", "location", "longitude", "manufacturer-id", "model-id", "orientation", "point", "ruleset-ids", "semi-major-axis", "semi-minor-axis", "serial-number", "type", "version"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.paws().notify_spectrum_use(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _paws_register(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _paws_register(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PawsRegisterRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1434,57 +1439,62 @@ impl Engine { request.type_ = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["adr", "antenna", "center", "code", "confidence", "country", "device-desc", "device-owner", "email", "etsi-en-device-category", "etsi-en-device-emissions-class", "etsi-en-device-type", "etsi-en-technology-id", "fcc-id", "fcc-tvbd-device-type", "fn", "height", "height-type", "height-uncertainty", "latitude", "locality", "location", "longitude", "manufacturer-id", "model-id", "operator", "org", "orientation", "owner", "pobox", "point", "region", "ruleset-ids", "semi-major-axis", "semi-minor-axis", "serial-number", "street", "tel", "text", "type", "uri", "version"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.paws().register(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _paws_verify_device(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _paws_verify_device(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::PawsVerifyDeviceRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1506,88 +1516,107 @@ impl Engine { request.type_ = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["type", "version"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.paws().verify_device(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_paws { - if self.opt.cmd_get_spectrum { - call_result = self._paws_get_spectrum(dry_run, &mut err); - } else if self.opt.cmd_get_spectrum_batch { - call_result = self._paws_get_spectrum_batch(dry_run, &mut err); - } else if self.opt.cmd_init { - call_result = self._paws_init(dry_run, &mut err); - } else if self.opt.cmd_notify_spectrum_use { - call_result = self._paws_notify_spectrum_use(dry_run, &mut err); - } else if self.opt.cmd_register { - call_result = self._paws_register(dry_run, &mut err); - } else if self.opt.cmd_verify_device { - call_result = self._paws_verify_device(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("paws", Some(opt)) => { + match opt.subcommand() { + ("get-spectrum", Some(opt)) => { + call_result = self._paws_get_spectrum(opt, dry_run, &mut err); + }, + ("get-spectrum-batch", Some(opt)) => { + call_result = self._paws_get_spectrum_batch(opt, dry_run, &mut err); + }, + ("init", Some(opt)) => { + call_result = self._paws_init(opt, dry_run, &mut err); + }, + ("notify-spectrum-use", Some(opt)) => { + call_result = self._paws_notify_spectrum_use(opt, dry_run, &mut err); + }, + ("register", Some(opt)) => { + call_result = self._paws_register(opt, dry_run, &mut err); + }, + ("verify-device", Some(opt)) => { + call_result = self._paws_verify_device(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("paws".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -1600,7 +1629,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1613,7 +1642,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1623,37 +1652,253 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Spectrum::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("paws", "methods: 'get-spectrum', 'get-spectrum-batch', 'init', 'notify-spectrum-use', 'register' and 'verify-device'", vec![ + ("get-spectrum", + Some(r##"Requests information about the available spectrum for a device at a location. Requests from a fixed-mode device must include owner information so the device can be registered with the database."##), + "Details at http://byron.github.io/google-apis-rs/google_spectrum1_explorer_cli/paws_get-spectrum", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get-spectrum-batch", + Some(r##"The Google Spectrum Database does not support batch requests, so this method always yields an UNIMPLEMENTED error."##), + "Details at http://byron.github.io/google-apis-rs/google_spectrum1_explorer_cli/paws_get-spectrum-batch", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("init", + Some(r##"Initializes the connection between a white space device and the database."##), + "Details at http://byron.github.io/google-apis-rs/google_spectrum1_explorer_cli/paws_init", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("notify-spectrum-use", + Some(r##"Notifies the database that the device has selected certain frequency ranges for transmission. Only to be invoked when required by the regulator. The Google Spectrum Database does not operate in domains that require notification, so this always yields an UNIMPLEMENTED error."##), + "Details at http://byron.github.io/google-apis-rs/google_spectrum1_explorer_cli/paws_notify-spectrum-use", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("register", + Some(r##"The Google Spectrum Database implements registration in the getSpectrum method. As such this always returns an UNIMPLEMENTED error."##), + "Details at http://byron.github.io/google-apis-rs/google_spectrum1_explorer_cli/paws_register", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("verify-device", + Some(r##"Validates a device for white space use in accordance with regulatory rules. The Google Spectrum Database does not support master/slave configurations, so this always yields an UNIMPLEMENTED error."##), + "Details at http://byron.github.io/google-apis-rs/google_spectrum1_explorer_cli/paws_verify-device", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("spectrum1-explorer") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150112") + .about("API for spectrum-management functions.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_spectrum1_explorer_cli") + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/spectrum1_explorer/Cargo.toml b/gen/spectrum1_explorer/Cargo.toml index 22a56a81de..a04c7f5df2 100644 --- a/gen/spectrum1_explorer/Cargo.toml +++ b/gen/spectrum1_explorer/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-spectrum1_explorer" -version = "0.1.6+20150112" +version = "0.1.7+20150112" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with spectrum (protocol v1explorer)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/spectrum1_explorer" @@ -15,9 +15,10 @@ keywords = ["spectrum", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/spectrum1_explorer/README.md b/gen/spectrum1_explorer/README.md index dd3ba21f99..46a5951e15 100644 --- a/gen/spectrum1_explorer/README.md +++ b/gen/spectrum1_explorer/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-spectrum1_explorer` library allows access to all features of the *Google spectrum* service. -This documentation was generated from *spectrum* crate version *0.1.6+20150112*, where *20150112* is the exact revision of the *spectrum:v1explorer* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *spectrum* crate version *0.1.7+20150112*, where *20150112* is the exact revision of the *spectrum:v1explorer* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *spectrum* *v1_explorer* API can be found at the [official documentation site](http://developers.google.com/spectrum). @@ -163,7 +163,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_spectrum1_explorer/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_spectrum1_explorer/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/spectrum1_explorer/src/cmn.rs b/gen/spectrum1_explorer/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/spectrum1_explorer/src/cmn.rs +++ b/gen/spectrum1_explorer/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/spectrum1_explorer/src/lib.rs b/gen/spectrum1_explorer/src/lib.rs index 2060832d1c..df9246035e 100644 --- a/gen/spectrum1_explorer/src/lib.rs +++ b/gen/spectrum1_explorer/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *spectrum* crate version *0.1.6+20150112*, where *20150112* is the exact revision of the *spectrum:v1explorer* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *spectrum* crate version *0.1.7+20150112*, where *20150112* is the exact revision of the *spectrum:v1explorer* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *spectrum* *v1_explorer* API can be found at the //! [official documentation site](http://developers.google.com/spectrum). @@ -164,7 +164,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -173,7 +173,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -189,6 +188,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -289,7 +289,7 @@ impl<'a, C, A> Spectrum<C, A> Spectrum { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -298,7 +298,7 @@ impl<'a, C, A> Spectrum<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1352,6 +1352,7 @@ impl<'a, C, A> PawNotifySpectrumUseCall<'a, C, A> where C: BorrowMut<hyper::Clie /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PawsNotifySpectrumUseResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1391,11 +1392,20 @@ impl<'a, C, A> PawNotifySpectrumUseCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1404,7 +1414,7 @@ impl<'a, C, A> PawNotifySpectrumUseCall<'a, C, A> where C: BorrowMut<hyper::Clie request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -1556,6 +1566,7 @@ impl<'a, C, A> PawRegisterCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PawsRegisterResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1595,11 +1606,20 @@ impl<'a, C, A> PawRegisterCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1608,7 +1628,7 @@ impl<'a, C, A> PawRegisterCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -1760,6 +1780,7 @@ impl<'a, C, A> PawGetSpectrumCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PawsGetSpectrumResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1799,11 +1820,20 @@ impl<'a, C, A> PawGetSpectrumCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1812,7 +1842,7 @@ impl<'a, C, A> PawGetSpectrumCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -1964,6 +1994,7 @@ impl<'a, C, A> PawInitCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PawsInitResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2003,11 +2034,20 @@ impl<'a, C, A> PawInitCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2016,7 +2056,7 @@ impl<'a, C, A> PawInitCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -2168,6 +2208,7 @@ impl<'a, C, A> PawGetSpectrumBatchCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PawsGetSpectrumBatchResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2207,11 +2248,20 @@ impl<'a, C, A> PawGetSpectrumBatchCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2220,7 +2270,7 @@ impl<'a, C, A> PawGetSpectrumBatchCall<'a, C, A> where C: BorrowMut<hyper::Clien request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) @@ -2372,6 +2422,7 @@ impl<'a, C, A> PawVerifyDeviceCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PawsVerifyDeviceResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2411,11 +2462,20 @@ impl<'a, C, A> PawVerifyDeviceCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2424,7 +2484,7 @@ impl<'a, C, A> PawVerifyDeviceCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(ContentType(json_mime_type.clone())) .header(ContentLength(request_size as u64)) diff --git a/gen/sqladmin1_beta4-cli/Cargo.toml b/gen/sqladmin1_beta4-cli/Cargo.toml index dabe8a9000..ea76785ff3 100644 --- a/gen/sqladmin1_beta4-cli/Cargo.toml +++ b/gen/sqladmin1_beta4-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-sqladmin1_beta4-cli" -version = "0.1.0+20150305" +version = "0.2.0+20150305" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with SQL Admin (protocol v1beta4)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/sqladmin1_beta4-cli" @@ -17,15 +17,14 @@ keywords = ["sqladmin", "google", "cli"] name = "sqladmin1-beta4" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-sqladmin1_beta4] path = "../sqladmin1_beta4" diff --git a/gen/sqladmin1_beta4-cli/README.md b/gen/sqladmin1_beta4-cli/README.md index e9e026cfee..12f1eeed1e 100644 --- a/gen/sqladmin1_beta4-cli/README.md +++ b/gen/sqladmin1_beta4-cli/README.md @@ -10,55 +10,64 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *SQL Admin* API can be found at the +[official documentation site](https://developers.google.com/cloud-sql/docs/admin-api/). + # Usage -This documentation was generated from the *SQL Admin* API at revision *20150305*. The CLI is at version *0.1.0*. +This documentation was generated from the *SQL Admin* API at revision *20150305*. The CLI is at version *0.2.0*. ```bash - sqladmin1-beta4 [options] backup-runs get <project> <instance> <id> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] backup-runs list <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] databases delete <project> <instance> <database> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] databases get <project> <instance> <database> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] databases insert <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] databases list <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] databases patch <project> <instance> <database> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] databases update <project> <instance> <database> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] flags list [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances clone <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances delete <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances export <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances get <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances import <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances insert <project> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances list <project> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances patch <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances promote-replica <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances reset-ssl-config <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances restart <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances restore-backup <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances start-replica <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances stop-replica <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances update <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] operations get <project> <operation> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] operations list <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] ssl-certs delete <project> <instance> <sha1-fingerprint> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] ssl-certs get <project> <instance> <sha1-fingerprint> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] ssl-certs insert <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] ssl-certs list <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] tiers list <project> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] users delete <project> <instance> <host> <name> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] users insert <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] users list <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] users update <project> <instance> <host> <name> -r <kv>... [-p <v>...] [-o <out>] +sqladmin1-beta4 [options] + backup-runs + get <project> <instance> <id> [-p <v>]... [-o <out>] + list <project> <instance> [-p <v>]... [-o <out>] + databases + delete <project> <instance> <database> [-p <v>]... [-o <out>] + get <project> <instance> <database> [-p <v>]... [-o <out>] + insert <project> <instance> (-r <kv>)... [-p <v>]... [-o <out>] + list <project> <instance> [-p <v>]... [-o <out>] + patch <project> <instance> <database> (-r <kv>)... [-p <v>]... [-o <out>] + update <project> <instance> <database> (-r <kv>)... [-p <v>]... [-o <out>] + flags + list [-p <v>]... [-o <out>] + instances + clone <project> <instance> (-r <kv>)... [-p <v>]... [-o <out>] + delete <project> <instance> [-p <v>]... [-o <out>] + export <project> <instance> (-r <kv>)... [-p <v>]... [-o <out>] + get <project> <instance> [-p <v>]... [-o <out>] + import <project> <instance> (-r <kv>)... [-p <v>]... [-o <out>] + insert <project> (-r <kv>)... [-p <v>]... [-o <out>] + list <project> [-p <v>]... [-o <out>] + patch <project> <instance> (-r <kv>)... [-p <v>]... [-o <out>] + promote-replica <project> <instance> [-p <v>]... [-o <out>] + reset-ssl-config <project> <instance> [-p <v>]... [-o <out>] + restart <project> <instance> [-p <v>]... [-o <out>] + restore-backup <project> <instance> (-r <kv>)... [-p <v>]... [-o <out>] + start-replica <project> <instance> [-p <v>]... [-o <out>] + stop-replica <project> <instance> [-p <v>]... [-o <out>] + update <project> <instance> (-r <kv>)... [-p <v>]... [-o <out>] + operations + get <project> <operation> [-p <v>]... [-o <out>] + list <project> <instance> [-p <v>]... [-o <out>] + ssl-certs + delete <project> <instance> <sha1-fingerprint> [-p <v>]... [-o <out>] + get <project> <instance> <sha1-fingerprint> [-p <v>]... [-o <out>] + insert <project> <instance> (-r <kv>)... [-p <v>]... [-o <out>] + list <project> <instance> [-p <v>]... [-o <out>] + tiers + list <project> [-p <v>]... [-o <out>] + users + delete <project> <instance> <host> <name> [-p <v>]... [-o <out>] + insert <project> <instance> (-r <kv>)... [-p <v>]... [-o <out>] + list <project> <instance> [-p <v>]... [-o <out>] + update <project> <instance> <host> <name> (-r <kv>)... [-p <v>]... [-o <out>] sqladmin1-beta4 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/sqladmin1_beta4-cli/mkdocs.yml b/gen/sqladmin1_beta4-cli/mkdocs.yml index 404678187d..985bf9ca8b 100644 --- a/gen/sqladmin1_beta4-cli/mkdocs.yml +++ b/gen/sqladmin1_beta4-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: SQL Admin v0.1.0+20150305 +site_name: SQL Admin v0.2.0+20150305 site_url: http://byron.github.io/google-apis-rs/google-sqladmin1_beta4-cli site_description: Write integrating applications with bcore diff --git a/gen/sqladmin1_beta4-cli/src/cmn.rs b/gen/sqladmin1_beta4-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/sqladmin1_beta4-cli/src/cmn.rs +++ b/gen/sqladmin1_beta4-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/sqladmin1_beta4-cli/src/main.rs b/gen/sqladmin1_beta4-cli/src/main.rs index d12c757197..0e66211925 100644 --- a/gen/sqladmin1_beta4-cli/src/main.rs +++ b/gen/sqladmin1_beta4-cli/src/main.rs @@ -2,147 +2,103 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_sqladmin1_beta4 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - sqladmin1-beta4 [options] backup-runs get <project> <instance> <id> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] backup-runs list <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] databases delete <project> <instance> <database> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] databases get <project> <instance> <database> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] databases insert <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] databases list <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] databases patch <project> <instance> <database> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] databases update <project> <instance> <database> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] flags list [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances clone <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances delete <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances export <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances get <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances import <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances insert <project> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances list <project> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances patch <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances promote-replica <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances reset-ssl-config <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances restart <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances restore-backup <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances start-replica <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances stop-replica <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] instances update <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] operations get <project> <operation> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] operations list <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] ssl-certs delete <project> <instance> <sha1-fingerprint> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] ssl-certs get <project> <instance> <sha1-fingerprint> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] ssl-certs insert <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] ssl-certs list <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] tiers list <project> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] users delete <project> <instance> <host> <name> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] users insert <project> <instance> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] users list <project> <instance> [-p <v>...] [-o <out>] - sqladmin1-beta4 [options] users update <project> <instance> <host> <name> -r <kv>... [-p <v>...] [-o <out>] - sqladmin1-beta4 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::SQLAdmin<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _backup_runs_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.backup_runs().get(&self.opt.arg_project, &self.opt.arg_instance, &self.opt.arg_id); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _backup_runs_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.backup_runs().get(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or(""), opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _backup_runs_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.backup_runs().list(&self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _backup_runs_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.backup_runs().list(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -151,144 +107,156 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _databases_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.databases().delete(&self.opt.arg_project, &self.opt.arg_instance, &self.opt.arg_database); - for parg in self.opt.arg_v.iter() { + fn _databases_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.databases().delete(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or(""), opt.value_of("database").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _databases_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.databases().get(&self.opt.arg_project, &self.opt.arg_instance, &self.opt.arg_database); - for parg in self.opt.arg_v.iter() { + fn _databases_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.databases().get(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or(""), opt.value_of("database").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _databases_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _databases_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Database::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -328,106 +296,115 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["charset", "collation", "etag", "instance", "kind", "name", "project", "self-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.databases().insert(request, &self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.databases().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _databases_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.databases().list(&self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _databases_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.databases().list(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _databases_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _databases_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Database::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -467,60 +444,65 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["charset", "collation", "etag", "instance", "kind", "name", "project", "self-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.databases().patch(request, &self.opt.arg_project, &self.opt.arg_instance, &self.opt.arg_database); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.databases().patch(request, opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or(""), opt.value_of("database").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _databases_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _databases_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Database::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -560,106 +542,115 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["charset", "collation", "etag", "instance", "kind", "name", "project", "self-link"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.databases().update(request, &self.opt.arg_project, &self.opt.arg_instance, &self.opt.arg_database); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.databases().update(request, opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or(""), opt.value_of("database").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _flags_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _flags_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.flags().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_clone(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _instances_clone(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InstancesCloneRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -708,106 +699,115 @@ impl Engine { request.clone_context.as_mut().unwrap().destination_instance_name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bin-log-coordinates", "bin-log-file-name", "bin-log-position", "clone-context", "destination-instance-name", "kind"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instances().clone(request, &self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instances().clone(request, opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.instances().delete(&self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _instances_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().delete(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_export(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _instances_export(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InstancesExportRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -873,106 +873,115 @@ impl Engine { request.export_context.as_mut().unwrap().sql_export_options.as_mut().unwrap().tables.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["csv-export-options", "databases", "export-context", "file-type", "kind", "select-query", "sql-export-options", "tables", "uri"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instances().export(request, &self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instances().export(request, opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.instances().get(&self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _instances_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().get(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_import(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _instances_import(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InstancesImportRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1028,60 +1037,65 @@ impl Engine { request.import_context.as_mut().unwrap().csv_import_options.as_mut().unwrap().columns.as_mut().unwrap().push(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["columns", "csv-import-options", "database", "file-type", "import-context", "kind", "table", "uri"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instances().import(request, &self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instances().import(request, opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _instances_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::DatabaseInstance::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1379,58 +1393,63 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["activation-policy", "authorized-gae-applications", "backup-configuration", "binary-log-enabled", "ca-certificate", "cert", "cert-serial-number", "client-certificate", "client-key", "common-name", "connect-retry-interval", "crash-safe-replication-enabled", "create-time", "current-disk-size", "database-replication-enabled", "database-version", "dump-file-path", "enabled", "etag", "expiration-time", "follow-gae-application", "host-port", "instance", "instance-type", "ip-configuration", "ipv4-enabled", "ipv6-address", "kind", "location-preference", "master-heartbeat-period", "master-instance-name", "max-disk-size", "mysql-replica-configuration", "name", "on-premises-configuration", "password", "pricing-plan", "project", "region", "replica-configuration", "replica-names", "replication-type", "require-ssl", "self-link", "server-ca-cert", "service-account-email-address", "settings", "settings-version", "sha1-fingerprint", "ssl-cipher", "start-time", "state", "tier", "username", "verify-server-certificate", "zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instances().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instances().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.instances().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _instances_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -1439,52 +1458,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _instances_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::DatabaseInstance::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1782,198 +1805,215 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["activation-policy", "authorized-gae-applications", "backup-configuration", "binary-log-enabled", "ca-certificate", "cert", "cert-serial-number", "client-certificate", "client-key", "common-name", "connect-retry-interval", "crash-safe-replication-enabled", "create-time", "current-disk-size", "database-replication-enabled", "database-version", "dump-file-path", "enabled", "etag", "expiration-time", "follow-gae-application", "host-port", "instance", "instance-type", "ip-configuration", "ipv4-enabled", "ipv6-address", "kind", "location-preference", "master-heartbeat-period", "master-instance-name", "max-disk-size", "mysql-replica-configuration", "name", "on-premises-configuration", "password", "pricing-plan", "project", "region", "replica-configuration", "replica-names", "replication-type", "require-ssl", "self-link", "server-ca-cert", "service-account-email-address", "settings", "settings-version", "sha1-fingerprint", "ssl-cipher", "start-time", "state", "tier", "username", "verify-server-certificate", "zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instances().patch(request, &self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instances().patch(request, opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_promote_replica(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.instances().promote_replica(&self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _instances_promote_replica(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().promote_replica(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_reset_ssl_config(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.instances().reset_ssl_config(&self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _instances_reset_ssl_config(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().reset_ssl_config(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_restart(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.instances().restart(&self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _instances_restart(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().restart(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_restore_backup(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _instances_restore_backup(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::InstancesRestoreBackupRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2003,152 +2043,165 @@ impl Engine { request.restore_backup_context.as_mut().unwrap().backup_run_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["backup-run-id", "kind", "restore-backup-context"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instances().restore_backup(request, &self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instances().restore_backup(request, opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_start_replica(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.instances().start_replica(&self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _instances_start_replica(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().start_replica(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_stop_replica(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.instances().stop_replica(&self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _instances_stop_replica(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.instances().stop_replica(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _instances_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _instances_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::DatabaseInstance::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2446,104 +2499,113 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["activation-policy", "authorized-gae-applications", "backup-configuration", "binary-log-enabled", "ca-certificate", "cert", "cert-serial-number", "client-certificate", "client-key", "common-name", "connect-retry-interval", "crash-safe-replication-enabled", "create-time", "current-disk-size", "database-replication-enabled", "database-version", "dump-file-path", "enabled", "etag", "expiration-time", "follow-gae-application", "host-port", "instance", "instance-type", "ip-configuration", "ipv4-enabled", "ipv6-address", "kind", "location-preference", "master-heartbeat-period", "master-instance-name", "max-disk-size", "mysql-replica-configuration", "name", "on-premises-configuration", "password", "pricing-plan", "project", "region", "replica-configuration", "replica-names", "replication-type", "require-ssl", "self-link", "server-ca-cert", "service-account-email-address", "settings", "settings-version", "sha1-fingerprint", "ssl-cipher", "start-time", "state", "tier", "username", "verify-server-certificate", "zone"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.instances().update(request, &self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.instances().update(request, opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _operations_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.operations().get(&self.opt.arg_project, &self.opt.arg_operation); - for parg in self.opt.arg_v.iter() { + fn _operations_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.operations().get(opt.value_of("project").unwrap_or(""), opt.value_of("operation").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _operations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.operations().list(&self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _operations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.operations().list(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -2552,144 +2614,156 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _ssl_certs_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.ssl_certs().delete(&self.opt.arg_project, &self.opt.arg_instance, &self.opt.arg_sha1_fingerprint); - for parg in self.opt.arg_v.iter() { + fn _ssl_certs_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.ssl_certs().delete(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or(""), opt.value_of("sha1-fingerprint").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _ssl_certs_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.ssl_certs().get(&self.opt.arg_project, &self.opt.arg_instance, &self.opt.arg_sha1_fingerprint); - for parg in self.opt.arg_v.iter() { + fn _ssl_certs_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.ssl_certs().get(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or(""), opt.value_of("sha1-fingerprint").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _ssl_certs_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _ssl_certs_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::SslCertsInsertRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2708,198 +2782,215 @@ impl Engine { request.common_name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["common-name"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.ssl_certs().insert(request, &self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.ssl_certs().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _ssl_certs_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.ssl_certs().list(&self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _ssl_certs_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.ssl_certs().list(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tiers_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tiers().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _tiers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tiers().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().delete(&self.opt.arg_project, &self.opt.arg_instance, &self.opt.arg_host, &self.opt.arg_name); - for parg in self.opt.arg_v.iter() { + fn _users_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().delete(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or(""), opt.value_of("host").unwrap_or(""), opt.value_of("name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::User::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2936,106 +3027,115 @@ impl Engine { request.password = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "host", "instance", "kind", "name", "password", "project"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().insert(request, &self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.users().list(&self.opt.arg_project, &self.opt.arg_instance); - for parg in self.opt.arg_v.iter() { + fn _users_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.users().list(opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _users_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _users_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::User::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3072,184 +3172,253 @@ impl Engine { request.password = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "host", "instance", "kind", "name", "password", "project"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.users().update(request, &self.opt.arg_project, &self.opt.arg_instance, &self.opt.arg_host, &self.opt.arg_name); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.users().update(request, opt.value_of("project").unwrap_or(""), opt.value_of("instance").unwrap_or(""), opt.value_of("host").unwrap_or(""), opt.value_of("name").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_backup_runs { - if self.opt.cmd_get { - call_result = self._backup_runs_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._backup_runs_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("backup-runs", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._backup_runs_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._backup_runs_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("backup-runs".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("databases", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._databases_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._databases_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._databases_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._databases_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._databases_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._databases_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("databases".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("flags", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._flags_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("flags".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("instances", Some(opt)) => { + match opt.subcommand() { + ("clone", Some(opt)) => { + call_result = self._instances_clone(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._instances_delete(opt, dry_run, &mut err); + }, + ("export", Some(opt)) => { + call_result = self._instances_export(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._instances_get(opt, dry_run, &mut err); + }, + ("import", Some(opt)) => { + call_result = self._instances_import(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._instances_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._instances_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._instances_patch(opt, dry_run, &mut err); + }, + ("promote-replica", Some(opt)) => { + call_result = self._instances_promote_replica(opt, dry_run, &mut err); + }, + ("reset-ssl-config", Some(opt)) => { + call_result = self._instances_reset_ssl_config(opt, dry_run, &mut err); + }, + ("restart", Some(opt)) => { + call_result = self._instances_restart(opt, dry_run, &mut err); + }, + ("restore-backup", Some(opt)) => { + call_result = self._instances_restore_backup(opt, dry_run, &mut err); + }, + ("start-replica", Some(opt)) => { + call_result = self._instances_start_replica(opt, dry_run, &mut err); + }, + ("stop-replica", Some(opt)) => { + call_result = self._instances_stop_replica(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._instances_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("instances".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("operations", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._operations_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._operations_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("operations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("ssl-certs", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._ssl_certs_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._ssl_certs_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._ssl_certs_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._ssl_certs_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("ssl-certs".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("tiers", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._tiers_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("tiers".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("users", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._users_delete(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._users_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._users_list(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._users_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("users".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_databases { - if self.opt.cmd_delete { - call_result = self._databases_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._databases_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._databases_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._databases_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._databases_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._databases_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_flags { - if self.opt.cmd_list { - call_result = self._flags_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_instances { - if self.opt.cmd_clone { - call_result = self._instances_clone(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._instances_delete(dry_run, &mut err); - } else if self.opt.cmd_export { - call_result = self._instances_export(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._instances_get(dry_run, &mut err); - } else if self.opt.cmd_import { - call_result = self._instances_import(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._instances_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._instances_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._instances_patch(dry_run, &mut err); - } else if self.opt.cmd_promote_replica { - call_result = self._instances_promote_replica(dry_run, &mut err); - } else if self.opt.cmd_reset_ssl_config { - call_result = self._instances_reset_ssl_config(dry_run, &mut err); - } else if self.opt.cmd_restart { - call_result = self._instances_restart(dry_run, &mut err); - } else if self.opt.cmd_restore_backup { - call_result = self._instances_restore_backup(dry_run, &mut err); - } else if self.opt.cmd_start_replica { - call_result = self._instances_start_replica(dry_run, &mut err); - } else if self.opt.cmd_stop_replica { - call_result = self._instances_stop_replica(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._instances_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_operations { - if self.opt.cmd_get { - call_result = self._operations_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._operations_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_ssl_certs { - if self.opt.cmd_delete { - call_result = self._ssl_certs_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._ssl_certs_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._ssl_certs_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._ssl_certs_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_tiers { - if self.opt.cmd_list { - call_result = self._tiers_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_users { - if self.opt.cmd_delete { - call_result = self._users_delete(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._users_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._users_list(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._users_update(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -3262,7 +3431,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -3275,7 +3444,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -3285,37 +3454,1241 @@ impl Engine { let engine = Engine { opt: opt, hub: api::SQLAdmin::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("backup-runs", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Retrieves a resource containing information about a backup run."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/backup-runs_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"id"##), + None, + Some(r##"The ID of this Backup Run."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists all backup runs associated with a given instance and configuration in the reverse chronological order of the enqueued time."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/backup-runs_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("databases", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes a resource containing information about a database inside a Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/databases_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Database instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"database"##), + None, + Some(r##"Name of the database to be deleted in the instance."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Retrieves a resource containing information about a database inside a Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/databases_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Database instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"database"##), + None, + Some(r##"Name of the database in the instance."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Inserts a resource containing information about a database inside a Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/databases_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Database instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists databases in the specified Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/databases_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project for which to list Cloud SQL instances."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a resource containing information about a database inside a Cloud SQL instance. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/databases_patch", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Database instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"database"##), + None, + Some(r##"Name of the database to be updated in the instance."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a resource containing information about a database inside a Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/databases_update", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Database instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"database"##), + None, + Some(r##"Name of the database to be updated in the instance."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("flags", "methods: 'list'", vec![ + ("list", + Some(r##"List all available database flags for Google Cloud SQL instances."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/flags_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("instances", "methods: 'clone', 'delete', 'export', 'get', 'import', 'insert', 'list', 'patch', 'promote-replica', 'reset-ssl-config', 'restart', 'restore-backup', 'start-replica', 'stop-replica' and 'update'", vec![ + ("clone", + Some(r##"Creates a Cloud SQL instance as a clone of the source instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_clone", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the source as well as the clone Cloud SQL instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"The ID of the Cloud SQL instance to be cloned (source). This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes a Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("export", + Some(r##"Exports data from a Cloud SQL instance to a Google Cloud Storage bucket as a MySQL dump file."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_export", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance to be exported."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Retrieves a resource containing information about a Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Database instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("import", + Some(r##"Imports data into a Cloud SQL instance from a MySQL dump file in Google Cloud Storage."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_import", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project to which the newly created Cloud SQL instances should belong."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists instances under a given project in the alphabetical order of the instance name."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project for which to list Cloud SQL instances."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates settings of a Cloud SQL instance. Caution: This is not a partial update, so you must include values for all the settings that you want to retain. For partial updates, use patch.. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_patch", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("promote-replica", + Some(r##"Promotes the read replica instance to be a stand-alone Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_promote-replica", + vec![ + (Some(r##"project"##), + None, + Some(r##"ID of the project that contains the read replica."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL read replica instance name."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("reset-ssl-config", + Some(r##"Deletes all client certificates and generates a new server SSL certificate for the instance. The changes will not take effect until the instance is restarted. Existing instances without a server certificate will need to call this once to set a server certificate."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_reset-ssl-config", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("restart", + Some(r##"Restarts a Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_restart", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance to be restarted."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("restore-backup", + Some(r##"Restores a backup of a Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_restore-backup", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("start-replica", + Some(r##"Starts the replication in the read replica instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_start-replica", + vec![ + (Some(r##"project"##), + None, + Some(r##"ID of the project that contains the read replica."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL read replica instance name."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("stop-replica", + Some(r##"Stops the replication in the read replica instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_stop-replica", + vec![ + (Some(r##"project"##), + None, + Some(r##"ID of the project that contains the read replica."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL read replica instance name."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates settings of a Cloud SQL instance. Caution: This is not a partial update, so you must include values for all the settings that you want to retain. For partial updates, use patch."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/instances_update", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("operations", "methods: 'get' and 'list'", vec![ + ("get", + Some(r##"Retrieves an instance operation that has been performed on an instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/operations_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"operation"##), + None, + Some(r##"Instance operation ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists all instance operations that have been performed on the given Cloud SQL instance in the reverse chronological order of the start time."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/operations_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("ssl-certs", "methods: 'delete', 'get', 'insert' and 'list'", vec![ + ("delete", + Some(r##"Deletes the SSL certificate. The change will not take effect until the instance is restarted."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/ssl-certs_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance to be deleted."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"sha1-fingerprint"##), + None, + Some(r##"Sha1 FingerPrint."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Retrieves a particular SSL certificate. Does not include the private key (required for usage). The private key must be saved from the response to initial creation."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/ssl-certs_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"sha1-fingerprint"##), + None, + Some(r##"Sha1 FingerPrint."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates an SSL certificate and returns it along with the private key and server certificate authority. The new certificate will not be usable until the instance is restarted."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/ssl-certs_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project to which the newly created Cloud SQL instances should belong."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists all of the current SSL certificates for the instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/ssl-certs_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project for which to list Cloud SQL instances."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Cloud SQL instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("tiers", "methods: 'list'", vec![ + ("list", + Some(r##"Lists all available service tiers for Google Cloud SQL, for example D1, D2. For related information, see Pricing."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/tiers_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project for which to list tiers."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("users", "methods: 'delete', 'insert', 'list' and 'update'", vec![ + ("delete", + Some(r##"Deletes a user from a Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/users_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Database instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"host"##), + None, + Some(r##"Host of the user in the instance."##), + Some(true), + Some(false)), + + (Some(r##"name"##), + None, + Some(r##"Name of the user in the instance."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new user in a Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/users_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Database instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists users in the specified Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/users_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Database instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an existing user in a Cloud SQL instance."##), + "Details at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli/users_update", + vec![ + (Some(r##"project"##), + None, + Some(r##"Project ID of the project that contains the instance."##), + Some(true), + Some(false)), + + (Some(r##"instance"##), + None, + Some(r##"Database instance ID. This does not include the project ID."##), + Some(true), + Some(false)), + + (Some(r##"host"##), + None, + Some(r##"Host of the user in the instance."##), + Some(true), + Some(false)), + + (Some(r##"name"##), + None, + Some(r##"Name of the user in the instance."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("sqladmin1-beta4") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150305") + .about("API for Cloud SQL database instance management.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_sqladmin1_beta4_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/sqladmin1_beta4/Cargo.toml b/gen/sqladmin1_beta4/Cargo.toml index 2f635edc50..c86d52c976 100644 --- a/gen/sqladmin1_beta4/Cargo.toml +++ b/gen/sqladmin1_beta4/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-sqladmin1_beta4" -version = "0.1.6+20150305" +version = "0.1.7+20150305" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with SQL Admin (protocol v1beta4)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/sqladmin1_beta4" @@ -15,9 +15,10 @@ keywords = ["sqladmin", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/sqladmin1_beta4/README.md b/gen/sqladmin1_beta4/README.md index 6704908abc..760ae8ae59 100644 --- a/gen/sqladmin1_beta4/README.md +++ b/gen/sqladmin1_beta4/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-sqladmin1_beta4` library allows access to all features of the *Google SQL Admin* service. -This documentation was generated from *SQL Admin* crate version *0.1.6+20150305*, where *20150305* is the exact revision of the *sqladmin:v1beta4* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *SQL Admin* crate version *0.1.7+20150305*, where *20150305* is the exact revision of the *sqladmin:v1beta4* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *SQL Admin* *v1_beta4* API can be found at the [official documentation site](https://developers.google.com/cloud-sql/docs/admin-api/). @@ -199,7 +199,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_sqladmin1_beta4/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_sqladmin1_beta4/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/sqladmin1_beta4/src/cmn.rs b/gen/sqladmin1_beta4/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/sqladmin1_beta4/src/cmn.rs +++ b/gen/sqladmin1_beta4/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/sqladmin1_beta4/src/lib.rs b/gen/sqladmin1_beta4/src/lib.rs index a376e0e097..bf46404977 100644 --- a/gen/sqladmin1_beta4/src/lib.rs +++ b/gen/sqladmin1_beta4/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *SQL Admin* crate version *0.1.6+20150305*, where *20150305* is the exact revision of the *sqladmin:v1beta4* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *SQL Admin* crate version *0.1.7+20150305*, where *20150305* is the exact revision of the *sqladmin:v1beta4* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *SQL Admin* *v1_beta4* API can be found at the //! [official documentation site](https://developers.google.com/cloud-sql/docs/admin-api/). @@ -200,7 +200,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -209,7 +209,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -225,6 +224,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -351,7 +351,7 @@ impl<'a, C, A> SQLAdmin<C, A> SQLAdmin { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -381,7 +381,7 @@ impl<'a, C, A> SQLAdmin<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -2665,7 +2665,7 @@ impl<'a, C, A> OperationListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2687,7 +2687,7 @@ impl<'a, C, A> OperationListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2930,7 +2930,7 @@ impl<'a, C, A> OperationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2952,7 +2952,7 @@ impl<'a, C, A> OperationGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3179,7 +3179,7 @@ impl<'a, C, A> TierListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3201,7 +3201,7 @@ impl<'a, C, A> TierListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3420,7 +3420,7 @@ impl<'a, C, A> UserListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3442,7 +3442,7 @@ impl<'a, C, A> UserListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3675,7 +3675,7 @@ impl<'a, C, A> UserDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3697,7 +3697,7 @@ impl<'a, C, A> UserDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3899,6 +3899,7 @@ impl<'a, C, A> UserUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3957,11 +3958,20 @@ impl<'a, C, A> UserUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3984,7 +3994,7 @@ impl<'a, C, A> UserUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4196,6 +4206,7 @@ impl<'a, C, A> UserInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4252,11 +4263,20 @@ impl<'a, C, A> UserInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4279,7 +4299,7 @@ impl<'a, C, A> UserInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4520,7 +4540,7 @@ impl<'a, C, A> InstanceResetSslConfigCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4542,7 +4562,7 @@ impl<'a, C, A> InstanceResetSslConfigCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4771,7 +4791,7 @@ impl<'a, C, A> InstancePromoteReplicaCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4793,7 +4813,7 @@ impl<'a, C, A> InstancePromoteReplicaCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5022,7 +5042,7 @@ impl<'a, C, A> InstanceGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5044,7 +5064,7 @@ impl<'a, C, A> InstanceGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5224,6 +5244,7 @@ impl<'a, C, A> InstancePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5280,11 +5301,20 @@ impl<'a, C, A> InstancePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5307,7 +5337,7 @@ impl<'a, C, A> InstancePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5548,7 +5578,7 @@ impl<'a, C, A> InstanceRestartCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5570,7 +5600,7 @@ impl<'a, C, A> InstanceRestartCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5799,7 +5829,7 @@ impl<'a, C, A> InstanceDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5821,7 +5851,7 @@ impl<'a, C, A> InstanceDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6050,7 +6080,7 @@ impl<'a, C, A> InstanceStopReplicaCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6072,7 +6102,7 @@ impl<'a, C, A> InstanceStopReplicaCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6301,7 +6331,7 @@ impl<'a, C, A> InstanceStartReplicaCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6323,7 +6353,7 @@ impl<'a, C, A> InstanceStartReplicaCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6502,6 +6532,7 @@ impl<'a, C, A> InstanceInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6557,11 +6588,20 @@ impl<'a, C, A> InstanceInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6584,7 +6624,7 @@ impl<'a, C, A> InstanceInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6823,7 +6863,7 @@ impl<'a, C, A> InstanceListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6845,7 +6885,7 @@ impl<'a, C, A> InstanceListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7029,6 +7069,7 @@ impl<'a, C, A> InstanceImportCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7085,11 +7126,20 @@ impl<'a, C, A> InstanceImportCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7112,7 +7162,7 @@ impl<'a, C, A> InstanceImportCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7304,6 +7354,7 @@ impl<'a, C, A> InstanceUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7360,11 +7411,20 @@ impl<'a, C, A> InstanceUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7387,7 +7447,7 @@ impl<'a, C, A> InstanceUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7579,6 +7639,7 @@ impl<'a, C, A> InstanceCloneCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7635,11 +7696,20 @@ impl<'a, C, A> InstanceCloneCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7662,7 +7732,7 @@ impl<'a, C, A> InstanceCloneCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7854,6 +7924,7 @@ impl<'a, C, A> InstanceExportCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7910,11 +7981,20 @@ impl<'a, C, A> InstanceExportCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7937,7 +8017,7 @@ impl<'a, C, A> InstanceExportCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8129,6 +8209,7 @@ impl<'a, C, A> InstanceRestoreBackupCall<'a, C, A> where C: BorrowMut<hyper::Cli /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8185,11 +8266,20 @@ impl<'a, C, A> InstanceRestoreBackupCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8212,7 +8302,7 @@ impl<'a, C, A> InstanceRestoreBackupCall<'a, C, A> where C: BorrowMut<hyper::Cli request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8425,7 +8515,7 @@ impl<'a, C, A> FlagListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8447,7 +8537,7 @@ impl<'a, C, A> FlagListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8658,7 +8748,7 @@ impl<'a, C, A> DatabaseDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8680,7 +8770,7 @@ impl<'a, C, A> DatabaseDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8871,6 +8961,7 @@ impl<'a, C, A> DatabasePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8928,11 +9019,20 @@ impl<'a, C, A> DatabasePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8955,7 +9055,7 @@ impl<'a, C, A> DatabasePatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9206,7 +9306,7 @@ impl<'a, C, A> DatabaseListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9228,7 +9328,7 @@ impl<'a, C, A> DatabaseListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9408,6 +9508,7 @@ impl<'a, C, A> DatabaseInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9464,11 +9565,20 @@ impl<'a, C, A> DatabaseInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9491,7 +9601,7 @@ impl<'a, C, A> DatabaseInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9734,7 +9844,7 @@ impl<'a, C, A> DatabaseGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9756,7 +9866,7 @@ impl<'a, C, A> DatabaseGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9947,6 +10057,7 @@ impl<'a, C, A> DatabaseUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Operation)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10004,11 +10115,20 @@ impl<'a, C, A> DatabaseUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10031,7 +10151,7 @@ impl<'a, C, A> DatabaseUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -10233,6 +10353,7 @@ impl<'a, C, A> SslCertInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, SslCertsInsertResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10289,11 +10410,20 @@ impl<'a, C, A> SslCertInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10316,7 +10446,7 @@ impl<'a, C, A> SslCertInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -10559,7 +10689,7 @@ impl<'a, C, A> SslCertDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10581,7 +10711,7 @@ impl<'a, C, A> SslCertDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10822,7 +10952,7 @@ impl<'a, C, A> SslCertGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10844,7 +10974,7 @@ impl<'a, C, A> SslCertGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11083,7 +11213,7 @@ impl<'a, C, A> SslCertListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11105,7 +11235,7 @@ impl<'a, C, A> SslCertListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11344,7 +11474,7 @@ impl<'a, C, A> BackupRunListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11366,7 +11496,7 @@ impl<'a, C, A> BackupRunListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11611,7 +11741,7 @@ impl<'a, C, A> BackupRunGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11633,7 +11763,7 @@ impl<'a, C, A> BackupRunGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/storage1-cli/Cargo.toml b/gen/storage1-cli/Cargo.toml index ab2b99c112..5d0e36d52d 100644 --- a/gen/storage1-cli/Cargo.toml +++ b/gen/storage1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-storage1-cli" -version = "0.1.0+20150326" +version = "0.2.0+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with storage (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/storage1-cli" @@ -17,15 +17,14 @@ keywords = ["storage", "google", "cli"] name = "storage1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-storage1] path = "../storage1" diff --git a/gen/storage1-cli/README.md b/gen/storage1-cli/README.md index 7ebe19a76e..4ca98b5914 100644 --- a/gen/storage1-cli/README.md +++ b/gen/storage1-cli/README.md @@ -10,55 +10,62 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *storage* API can be found at the +[official documentation site](https://developers.google.com/storage/docs/json_api/). + # Usage -This documentation was generated from the *storage* API at revision *20150326*. The CLI is at version *0.1.0*. +This documentation was generated from the *storage* API at revision *20150326*. The CLI is at version *0.2.0*. ```bash - storage1 [options] bucket-access-controls delete <bucket> <entity> [-p <v>...] - storage1 [options] bucket-access-controls get <bucket> <entity> [-p <v>...] [-o <out>] - storage1 [options] bucket-access-controls insert <bucket> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] bucket-access-controls list <bucket> [-p <v>...] [-o <out>] - storage1 [options] bucket-access-controls patch <bucket> <entity> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] bucket-access-controls update <bucket> <entity> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] buckets delete <bucket> [-p <v>...] - storage1 [options] buckets get <bucket> [-p <v>...] [-o <out>] - storage1 [options] buckets insert <project> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] buckets list <project> [-p <v>...] [-o <out>] - storage1 [options] buckets patch <bucket> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] buckets update <bucket> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] channels stop -r <kv>... [-p <v>...] - storage1 [options] default-object-access-controls delete <bucket> <entity> [-p <v>...] - storage1 [options] default-object-access-controls get <bucket> <entity> [-p <v>...] [-o <out>] - storage1 [options] default-object-access-controls insert <bucket> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] default-object-access-controls list <bucket> [-p <v>...] [-o <out>] - storage1 [options] default-object-access-controls patch <bucket> <entity> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] default-object-access-controls update <bucket> <entity> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] object-access-controls delete <bucket> <object> <entity> [-p <v>...] - storage1 [options] object-access-controls get <bucket> <object> <entity> [-p <v>...] [-o <out>] - storage1 [options] object-access-controls insert <bucket> <object> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] object-access-controls list <bucket> <object> [-p <v>...] [-o <out>] - storage1 [options] object-access-controls patch <bucket> <object> <entity> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] object-access-controls update <bucket> <object> <entity> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] objects compose <destination-bucket> <destination-object> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] objects copy <source-bucket> <source-object> <destination-bucket> <destination-object> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] objects delete <bucket> <object> [-p <v>...] - storage1 [options] objects get <bucket> <object> [-p <v>...] [-o <out>] - storage1 [options] objects insert <bucket> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - storage1 [options] objects list <bucket> [-p <v>...] [-o <out>] - storage1 [options] objects patch <bucket> <object> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] objects rewrite <source-bucket> <source-object> <destination-bucket> <destination-object> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] objects update <bucket> <object> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] objects watch-all <bucket> -r <kv>... [-p <v>...] [-o <out>] +storage1 [options] + bucket-access-controls + delete <bucket> <entity> [-p <v>]... + get <bucket> <entity> [-p <v>]... [-o <out>] + insert <bucket> (-r <kv>)... [-p <v>]... [-o <out>] + list <bucket> [-p <v>]... [-o <out>] + patch <bucket> <entity> (-r <kv>)... [-p <v>]... [-o <out>] + update <bucket> <entity> (-r <kv>)... [-p <v>]... [-o <out>] + buckets + delete <bucket> [-p <v>]... + get <bucket> [-p <v>]... [-o <out>] + insert <project> (-r <kv>)... [-p <v>]... [-o <out>] + list <project> [-p <v>]... [-o <out>] + patch <bucket> (-r <kv>)... [-p <v>]... [-o <out>] + update <bucket> (-r <kv>)... [-p <v>]... [-o <out>] + channels + stop (-r <kv>)... [-p <v>]... + default-object-access-controls + delete <bucket> <entity> [-p <v>]... + get <bucket> <entity> [-p <v>]... [-o <out>] + insert <bucket> (-r <kv>)... [-p <v>]... [-o <out>] + list <bucket> [-p <v>]... [-o <out>] + patch <bucket> <entity> (-r <kv>)... [-p <v>]... [-o <out>] + update <bucket> <entity> (-r <kv>)... [-p <v>]... [-o <out>] + object-access-controls + delete <bucket> <object> <entity> [-p <v>]... + get <bucket> <object> <entity> [-p <v>]... [-o <out>] + insert <bucket> <object> (-r <kv>)... [-p <v>]... [-o <out>] + list <bucket> <object> [-p <v>]... [-o <out>] + patch <bucket> <object> <entity> (-r <kv>)... [-p <v>]... [-o <out>] + update <bucket> <object> <entity> (-r <kv>)... [-p <v>]... [-o <out>] + objects + compose <destination-bucket> <destination-object> (-r <kv>)... [-p <v>]... [-o <out>] + copy <source-bucket> <source-object> <destination-bucket> <destination-object> (-r <kv>)... [-p <v>]... [-o <out>] + delete <bucket> <object> [-p <v>]... + get <bucket> <object> [-p <v>]... [-o <out>] + insert <bucket> (-r <kv>)... (-u (simple|resumable) -f <file> [-m <mime>]) [-p <v>]... [-o <out>] + list <bucket> [-p <v>]... [-o <out>] + patch <bucket> <object> (-r <kv>)... [-p <v>]... [-o <out>] + rewrite <source-bucket> <source-object> <destination-bucket> <destination-object> (-r <kv>)... [-p <v>]... [-o <out>] + update <bucket> <object> (-r <kv>)... [-p <v>]... [-o <out>] + watch-all <bucket> (-r <kv>)... [-p <v>]... [-o <out>] storage1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_storage1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/storage1-cli/mkdocs.yml b/gen/storage1-cli/mkdocs.yml index c08fdc09fe..b94114bb57 100644 --- a/gen/storage1-cli/mkdocs.yml +++ b/gen/storage1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: storage v0.1.0+20150326 +site_name: storage v0.2.0+20150326 site_url: http://byron.github.io/google-apis-rs/google-storage1-cli site_description: Write integrating applications with bcore diff --git a/gen/storage1-cli/src/cmn.rs b/gen/storage1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/storage1-cli/src/cmn.rs +++ b/gen/storage1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/storage1-cli/src/main.rs b/gen/storage1-cli/src/main.rs index 4390ccf1d4..94c31bcfb1 100644 --- a/gen/storage1-cli/src/main.rs +++ b/gen/storage1-cli/src/main.rs @@ -2,193 +2,148 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_storage1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - storage1 [options] bucket-access-controls delete <bucket> <entity> [-p <v>...] - storage1 [options] bucket-access-controls get <bucket> <entity> [-p <v>...] [-o <out>] - storage1 [options] bucket-access-controls insert <bucket> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] bucket-access-controls list <bucket> [-p <v>...] [-o <out>] - storage1 [options] bucket-access-controls patch <bucket> <entity> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] bucket-access-controls update <bucket> <entity> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] buckets delete <bucket> [-p <v>...] - storage1 [options] buckets get <bucket> [-p <v>...] [-o <out>] - storage1 [options] buckets insert <project> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] buckets list <project> [-p <v>...] [-o <out>] - storage1 [options] buckets patch <bucket> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] buckets update <bucket> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] channels stop -r <kv>... [-p <v>...] - storage1 [options] default-object-access-controls delete <bucket> <entity> [-p <v>...] - storage1 [options] default-object-access-controls get <bucket> <entity> [-p <v>...] [-o <out>] - storage1 [options] default-object-access-controls insert <bucket> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] default-object-access-controls list <bucket> [-p <v>...] [-o <out>] - storage1 [options] default-object-access-controls patch <bucket> <entity> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] default-object-access-controls update <bucket> <entity> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] object-access-controls delete <bucket> <object> <entity> [-p <v>...] - storage1 [options] object-access-controls get <bucket> <object> <entity> [-p <v>...] [-o <out>] - storage1 [options] object-access-controls insert <bucket> <object> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] object-access-controls list <bucket> <object> [-p <v>...] [-o <out>] - storage1 [options] object-access-controls patch <bucket> <object> <entity> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] object-access-controls update <bucket> <object> <entity> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] objects compose <destination-bucket> <destination-object> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] objects copy <source-bucket> <source-object> <destination-bucket> <destination-object> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] objects delete <bucket> <object> [-p <v>...] - storage1 [options] objects get <bucket> <object> [-p <v>...] [-o <out>] - storage1 [options] objects insert <bucket> -r <kv>... -u (simple|resumable) <file> <mime> [-p <v>...] [-o <out>] - storage1 [options] objects list <bucket> [-p <v>...] [-o <out>] - storage1 [options] objects patch <bucket> <object> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] objects rewrite <source-bucket> <source-object> <destination-bucket> <destination-object> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] objects update <bucket> <object> -r <kv>... [-p <v>...] [-o <out>] - storage1 [options] objects watch-all <bucket> -r <kv>... [-p <v>...] [-o <out>] - storage1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_storage1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Storage<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _bucket_access_controls_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.bucket_access_controls().delete(&self.opt.arg_bucket, &self.opt.arg_entity); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _bucket_access_controls_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.bucket_access_controls().delete(opt.value_of("bucket").unwrap_or(""), opt.value_of("entity").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _bucket_access_controls_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.bucket_access_controls().get(&self.opt.arg_bucket, &self.opt.arg_entity); - for parg in self.opt.arg_v.iter() { + fn _bucket_access_controls_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.bucket_access_controls().get(opt.value_of("bucket").unwrap_or(""), opt.value_of("entity").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _bucket_access_controls_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _bucket_access_controls_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::BucketAccessControl::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -250,106 +205,115 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "domain", "email", "entity", "entity-id", "etag", "id", "kind", "project-number", "project-team", "role", "self-link", "team"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.bucket_access_controls().insert(request, &self.opt.arg_bucket); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.bucket_access_controls().insert(request, opt.value_of("bucket").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _bucket_access_controls_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.bucket_access_controls().list(&self.opt.arg_bucket); - for parg in self.opt.arg_v.iter() { + fn _bucket_access_controls_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.bucket_access_controls().list(opt.value_of("bucket").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _bucket_access_controls_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _bucket_access_controls_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::BucketAccessControl::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -411,60 +375,65 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "domain", "email", "entity", "entity-id", "etag", "id", "kind", "project-number", "project-team", "role", "self-link", "team"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.bucket_access_controls().patch(request, &self.opt.arg_bucket, &self.opt.arg_entity); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.bucket_access_controls().patch(request, opt.value_of("bucket").unwrap_or(""), opt.value_of("entity").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _bucket_access_controls_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _bucket_access_controls_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::BucketAccessControl::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -526,58 +495,63 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "domain", "email", "entity", "entity-id", "etag", "id", "kind", "project-number", "project-team", "role", "self-link", "team"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.bucket_access_controls().update(request, &self.opt.arg_bucket, &self.opt.arg_entity); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.bucket_access_controls().update(request, opt.value_of("bucket").unwrap_or(""), opt.value_of("entity").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _buckets_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.buckets().delete(&self.opt.arg_bucket); - for parg in self.opt.arg_v.iter() { + fn _buckets_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.buckets().delete(opt.value_of("bucket").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "if-metageneration-not-match" => { @@ -586,48 +560,47 @@ impl Engine { "if-metageneration-match" => { call = call.if_metageneration_match(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["if-metageneration-not-match", "if-metageneration-match"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _buckets_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.buckets().get(&self.opt.arg_bucket); - for parg in self.opt.arg_v.iter() { + fn _buckets_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.buckets().get(opt.value_of("bucket").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { @@ -639,52 +612,56 @@ impl Engine { "if-metageneration-match" => { call = call.if_metageneration_match(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["if-metageneration-match", "if-metageneration-not-match", "projection"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _buckets_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _buckets_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Bucket::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -792,12 +769,13 @@ impl Engine { request.storage_class = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["enabled", "entity", "entity-id", "etag", "id", "kind", "location", "log-bucket", "log-object-prefix", "logging", "main-page-suffix", "metageneration", "name", "not-found-page", "owner", "project-number", "self-link", "storage-class", "time-created", "versioning", "website"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.buckets().insert(request, &self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.buckets().insert(request, opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { @@ -809,50 +787,54 @@ impl Engine { "predefined-acl" => { call = call.predefined_acl(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["predefined-acl", "projection", "predefined-default-object-acl"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _buckets_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.buckets().list(&self.opt.arg_project); - for parg in self.opt.arg_v.iter() { + fn _buckets_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.buckets().list(opt.value_of("project").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { @@ -867,52 +849,56 @@ impl Engine { "max-results" => { call = call.max_results(arg_from_str(value.unwrap_or("-0"), err, "max-results", "integer")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "prefix", "projection", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _buckets_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _buckets_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Bucket::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1020,12 +1006,13 @@ impl Engine { request.storage_class = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["enabled", "entity", "entity-id", "etag", "id", "kind", "location", "log-bucket", "log-object-prefix", "logging", "main-page-suffix", "metageneration", "name", "not-found-page", "owner", "project-number", "self-link", "storage-class", "time-created", "versioning", "website"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.buckets().patch(request, &self.opt.arg_bucket); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.buckets().patch(request, opt.value_of("bucket").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { @@ -1043,52 +1030,56 @@ impl Engine { "if-metageneration-match" => { call = call.if_metageneration_match(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["if-metageneration-match", "if-metageneration-not-match", "predefined-acl", "projection", "predefined-default-object-acl"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _buckets_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _buckets_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Bucket::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1196,12 +1187,13 @@ impl Engine { request.storage_class = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["enabled", "entity", "entity-id", "etag", "id", "kind", "location", "log-bucket", "log-object-prefix", "logging", "main-page-suffix", "metageneration", "name", "not-found-page", "owner", "project-number", "self-link", "storage-class", "time-created", "versioning", "website"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.buckets().update(request, &self.opt.arg_bucket); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.buckets().update(request, opt.value_of("bucket").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { @@ -1219,52 +1211,56 @@ impl Engine { "if-metageneration-match" => { call = call.if_metageneration_match(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["if-metageneration-match", "if-metageneration-not-match", "predefined-acl", "projection", "predefined-default-object-acl"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _channels_stop(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _channels_stop(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Channel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1314,148 +1310,151 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.channels().stop(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _default_object_access_controls_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.default_object_access_controls().delete(&self.opt.arg_bucket, &self.opt.arg_entity); - for parg in self.opt.arg_v.iter() { + fn _default_object_access_controls_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.default_object_access_controls().delete(opt.value_of("bucket").unwrap_or(""), opt.value_of("entity").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _default_object_access_controls_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.default_object_access_controls().get(&self.opt.arg_bucket, &self.opt.arg_entity); - for parg in self.opt.arg_v.iter() { + fn _default_object_access_controls_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.default_object_access_controls().get(opt.value_of("bucket").unwrap_or(""), opt.value_of("entity").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _default_object_access_controls_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _default_object_access_controls_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ObjectAccessControl::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1523,58 +1522,63 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "domain", "email", "entity", "entity-id", "etag", "generation", "id", "kind", "object", "project-number", "project-team", "role", "self-link", "team"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.default_object_access_controls().insert(request, &self.opt.arg_bucket); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.default_object_access_controls().insert(request, opt.value_of("bucket").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _default_object_access_controls_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.default_object_access_controls().list(&self.opt.arg_bucket); - for parg in self.opt.arg_v.iter() { + fn _default_object_access_controls_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.default_object_access_controls().list(opt.value_of("bucket").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "if-metageneration-not-match" => { @@ -1583,52 +1587,56 @@ impl Engine { "if-metageneration-match" => { call = call.if_metageneration_match(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["if-metageneration-not-match", "if-metageneration-match"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _default_object_access_controls_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _default_object_access_controls_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ObjectAccessControl::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1696,60 +1704,65 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "domain", "email", "entity", "entity-id", "etag", "generation", "id", "kind", "object", "project-number", "project-team", "role", "self-link", "team"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.default_object_access_controls().patch(request, &self.opt.arg_bucket, &self.opt.arg_entity); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.default_object_access_controls().patch(request, opt.value_of("bucket").unwrap_or(""), opt.value_of("entity").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _default_object_access_controls_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _default_object_access_controls_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ObjectAccessControl::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1817,156 +1830,164 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "domain", "email", "entity", "entity-id", "etag", "generation", "id", "kind", "object", "project-number", "project-team", "role", "self-link", "team"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.default_object_access_controls().update(request, &self.opt.arg_bucket, &self.opt.arg_entity); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.default_object_access_controls().update(request, opt.value_of("bucket").unwrap_or(""), opt.value_of("entity").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _object_access_controls_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.object_access_controls().delete(&self.opt.arg_bucket, &self.opt.arg_object, &self.opt.arg_entity); - for parg in self.opt.arg_v.iter() { + fn _object_access_controls_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.object_access_controls().delete(opt.value_of("bucket").unwrap_or(""), opt.value_of("object").unwrap_or(""), opt.value_of("entity").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "generation" => { call = call.generation(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["generation"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _object_access_controls_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.object_access_controls().get(&self.opt.arg_bucket, &self.opt.arg_object, &self.opt.arg_entity); - for parg in self.opt.arg_v.iter() { + fn _object_access_controls_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.object_access_controls().get(opt.value_of("bucket").unwrap_or(""), opt.value_of("object").unwrap_or(""), opt.value_of("entity").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "generation" => { call = call.generation(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["generation"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _object_access_controls_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _object_access_controls_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ObjectAccessControl::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2034,112 +2055,121 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "domain", "email", "entity", "entity-id", "etag", "generation", "id", "kind", "object", "project-number", "project-team", "role", "self-link", "team"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.object_access_controls().insert(request, &self.opt.arg_bucket, &self.opt.arg_object); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.object_access_controls().insert(request, opt.value_of("bucket").unwrap_or(""), opt.value_of("object").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "generation" => { call = call.generation(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["generation"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _object_access_controls_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.object_access_controls().list(&self.opt.arg_bucket, &self.opt.arg_object); - for parg in self.opt.arg_v.iter() { + fn _object_access_controls_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.object_access_controls().list(opt.value_of("bucket").unwrap_or(""), opt.value_of("object").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "generation" => { call = call.generation(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["generation"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _object_access_controls_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _object_access_controls_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ObjectAccessControl::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2207,63 +2237,68 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "domain", "email", "entity", "entity-id", "etag", "generation", "id", "kind", "object", "project-number", "project-team", "role", "self-link", "team"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.object_access_controls().patch(request, &self.opt.arg_bucket, &self.opt.arg_object, &self.opt.arg_entity); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.object_access_controls().patch(request, opt.value_of("bucket").unwrap_or(""), opt.value_of("object").unwrap_or(""), opt.value_of("entity").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "generation" => { call = call.generation(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["generation"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _object_access_controls_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _object_access_controls_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ObjectAccessControl::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2331,63 +2366,68 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "domain", "email", "entity", "entity-id", "etag", "generation", "id", "kind", "object", "project-number", "project-team", "role", "self-link", "team"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.object_access_controls().update(request, &self.opt.arg_bucket, &self.opt.arg_object, &self.opt.arg_entity); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.object_access_controls().update(request, opt.value_of("bucket").unwrap_or(""), opt.value_of("object").unwrap_or(""), opt.value_of("entity").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "generation" => { call = call.generation(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["generation"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _objects_compose(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _objects_compose(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ComposeRequest::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2519,13 +2559,14 @@ impl Engine { request.destination.as_mut().unwrap().content_disposition = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "cache-control", "component-count", "content-disposition", "content-encoding", "content-language", "content-type", "crc32c", "destination", "entity", "entity-id", "etag", "generation", "id", "kind", "md5-hash", "media-link", "metadata", "metageneration", "name", "owner", "self-link", "size", "storage-class", "time-deleted", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut download_mode = false; - let mut call = self.hub.objects().compose(request, &self.opt.arg_destination_bucket, &self.opt.arg_destination_object); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.objects().compose(request, opt.value_of("destination-bucket").unwrap_or(""), opt.value_of("destination-object").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "if-metageneration-match" => { @@ -2537,59 +2578,63 @@ impl Engine { "destination-predefined-acl" => { call = call.destination_predefined_acl(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["if-metageneration-match", "if-generation-match", "destination-predefined-acl"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { if !download_mode { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); } else { io::copy(&mut response, &mut ostream).unwrap(); } - None + Ok(()) } } } } - fn _objects_copy(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _objects_copy(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Object::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2707,13 +2752,14 @@ impl Engine { request.content_disposition = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "cache-control", "component-count", "content-disposition", "content-encoding", "content-language", "content-type", "crc32c", "entity", "entity-id", "etag", "generation", "id", "kind", "md5-hash", "media-link", "metadata", "metageneration", "name", "owner", "self-link", "size", "storage-class", "time-deleted", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut download_mode = false; - let mut call = self.hub.objects().copy(request, &self.opt.arg_source_bucket, &self.opt.arg_source_object, &self.opt.arg_destination_bucket, &self.opt.arg_destination_object); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.objects().copy(request, opt.value_of("source-bucket").unwrap_or(""), opt.value_of("source-object").unwrap_or(""), opt.value_of("destination-bucket").unwrap_or(""), opt.value_of("destination-object").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source-generation" => { @@ -2749,57 +2795,61 @@ impl Engine { "destination-predefined-acl" => { call = call.destination_predefined_acl(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["if-source-generation-match", "projection", "if-source-metageneration-not-match", "if-metageneration-not-match", "source-generation", "destination-predefined-acl", "if-source-generation-not-match", "if-source-metageneration-match", "if-generation-match", "if-metageneration-match", "if-generation-not-match"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { if !download_mode { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); } else { io::copy(&mut response, &mut ostream).unwrap(); } - None + Ok(()) } } } } - fn _objects_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.objects().delete(&self.opt.arg_bucket, &self.opt.arg_object); - for parg in self.opt.arg_v.iter() { + fn _objects_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.objects().delete(opt.value_of("bucket").unwrap_or(""), opt.value_of("object").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "if-metageneration-not-match" => { @@ -2817,49 +2867,48 @@ impl Engine { "generation" => { call = call.generation(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["generation", "if-metageneration-not-match", "if-generation-match", "if-metageneration-match", "if-generation-not-match"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _objects_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _objects_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut download_mode = false; - let mut call = self.hub.objects().get(&self.opt.arg_bucket, &self.opt.arg_object); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.objects().get(opt.value_of("bucket").unwrap_or(""), opt.value_of("object").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { @@ -2880,59 +2929,63 @@ impl Engine { "generation" => { call = call.generation(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["projection", "generation", "if-metageneration-match", "if-generation-match", "if-metageneration-not-match", "if-generation-not-match"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { if !download_mode { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); } else { io::copy(&mut response, &mut ostream).unwrap(); } - None + Ok(()) } } } } - fn _objects_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _objects_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Object::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3050,12 +3103,13 @@ impl Engine { request.content_disposition = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "cache-control", "component-count", "content-disposition", "content-encoding", "content-language", "content-type", "crc32c", "entity", "entity-id", "etag", "generation", "id", "kind", "md5-hash", "media-link", "metadata", "metageneration", "name", "owner", "self-link", "size", "storage-class", "time-deleted", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.objects().insert(request, &self.opt.arg_bucket); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.objects().insert(request, opt.value_of("bucket").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { @@ -3082,61 +3136,59 @@ impl Engine { "content-encoding" => { call = call.content_encoding(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["if-generation-match", "if-generation-not-match", "content-encoding", "if-metageneration-match", "name", "predefined-acl", "if-metageneration-not-match", "projection"] + )); + } + } } } - let protocol = - if self.opt.cmd_simple { - "simple" - } else if self.opt.cmd_resumable { - "resumable" - } else { - unreachable!() - }; - let mut input_file = input_file_from_opts(&self.opt.arg_file, err); - let mime_type = input_mime_from_opts(&self.opt.arg_mime, err); + let vals = opt.values_of("mode").unwrap(); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let mut input_file = input_file_from_opts(vals[1], err); + let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "simple" => call.upload(input_file.unwrap(), mime_type.unwrap()), - "resumable" => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), - _ => unreachable!(), + CallType::Upload(UploadProtocol::Simple) => call.upload(input_file.unwrap(), mime_type.unwrap()), + CallType::Upload(UploadProtocol::Resumable) => call.upload_resumable(input_file.unwrap(), mime_type.unwrap()), + CallType::Standard => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); io::copy(&mut response, &mut ostream).unwrap(); - None + Ok(()) } } } } - fn _objects_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.objects().list(&self.opt.arg_bucket); - for parg in self.opt.arg_v.iter() { + fn _objects_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.objects().list(opt.value_of("bucket").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "versions" => { @@ -3157,52 +3209,56 @@ impl Engine { "delimiter" => { call = call.delimiter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["projection", "versions", "prefix", "max-results", "page-token", "delimiter"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _objects_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _objects_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Object::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3320,12 +3376,13 @@ impl Engine { request.content_disposition = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "cache-control", "component-count", "content-disposition", "content-encoding", "content-language", "content-type", "crc32c", "entity", "entity-id", "etag", "generation", "id", "kind", "md5-hash", "media-link", "metadata", "metageneration", "name", "owner", "self-link", "size", "storage-class", "time-deleted", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.objects().patch(request, &self.opt.arg_bucket, &self.opt.arg_object); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.objects().patch(request, opt.value_of("bucket").unwrap_or(""), opt.value_of("object").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { @@ -3349,52 +3406,56 @@ impl Engine { "generation" => { call = call.generation(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["if-generation-match", "projection", "generation", "if-metageneration-match", "predefined-acl", "if-metageneration-not-match", "if-generation-not-match"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _objects_rewrite(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _objects_rewrite(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Object::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3512,12 +3573,13 @@ impl Engine { request.content_disposition = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "cache-control", "component-count", "content-disposition", "content-encoding", "content-language", "content-type", "crc32c", "entity", "entity-id", "etag", "generation", "id", "kind", "md5-hash", "media-link", "metadata", "metageneration", "name", "owner", "self-link", "size", "storage-class", "time-deleted", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.objects().rewrite(request, &self.opt.arg_source_bucket, &self.opt.arg_source_object, &self.opt.arg_destination_bucket, &self.opt.arg_destination_object); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.objects().rewrite(request, opt.value_of("source-bucket").unwrap_or(""), opt.value_of("source-object").unwrap_or(""), opt.value_of("destination-bucket").unwrap_or(""), opt.value_of("destination-object").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source-generation" => { @@ -3559,52 +3621,56 @@ impl Engine { "destination-predefined-acl" => { call = call.destination_predefined_acl(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["if-source-generation-match", "if-generation-match", "projection", "if-source-metageneration-not-match", "if-metageneration-not-match", "source-generation", "max-bytes-rewritten-per-call", "if-source-generation-not-match", "destination-predefined-acl", "if-source-metageneration-match", "rewrite-token", "if-metageneration-match", "if-generation-not-match"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _objects_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _objects_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Object::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3722,13 +3788,14 @@ impl Engine { request.content_disposition = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["bucket", "cache-control", "component-count", "content-disposition", "content-encoding", "content-language", "content-type", "crc32c", "entity", "entity-id", "etag", "generation", "id", "kind", "md5-hash", "media-link", "metadata", "metageneration", "name", "owner", "self-link", "size", "storage-class", "time-deleted", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut download_mode = false; - let mut call = self.hub.objects().update(request, &self.opt.arg_bucket, &self.opt.arg_object); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.objects().update(request, opt.value_of("bucket").unwrap_or(""), opt.value_of("object").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { @@ -3752,59 +3819,63 @@ impl Engine { "generation" => { call = call.generation(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["if-generation-match", "projection", "generation", "if-metageneration-match", "predefined-acl", "if-metageneration-not-match", "if-generation-not-match"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { if !download_mode { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); } else { io::copy(&mut response, &mut ostream).unwrap(); } - None + Ok(()) } } } } - fn _objects_watch_all(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _objects_watch_all(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Channel::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3854,12 +3925,13 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["address", "expiration", "id", "kind", "params", "payload", "resource-id", "resource-uri", "token", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.objects().watch_all(request, &self.opt.arg_bucket); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.objects().watch_all(request, opt.value_of("bucket").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "versions" => { @@ -3880,166 +3952,228 @@ impl Engine { "delimiter" => { call = call.delimiter(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["projection", "versions", "prefix", "max-results", "page-token", "delimiter"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_bucket_access_controls { - if self.opt.cmd_delete { - call_result = self._bucket_access_controls_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._bucket_access_controls_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._bucket_access_controls_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._bucket_access_controls_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._bucket_access_controls_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._bucket_access_controls_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("bucket-access-controls", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._bucket_access_controls_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._bucket_access_controls_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._bucket_access_controls_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._bucket_access_controls_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._bucket_access_controls_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._bucket_access_controls_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("bucket-access-controls".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("buckets", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._buckets_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._buckets_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._buckets_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._buckets_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._buckets_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._buckets_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("buckets".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("channels", Some(opt)) => { + match opt.subcommand() { + ("stop", Some(opt)) => { + call_result = self._channels_stop(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("channels".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("default-object-access-controls", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._default_object_access_controls_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._default_object_access_controls_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._default_object_access_controls_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._default_object_access_controls_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._default_object_access_controls_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._default_object_access_controls_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("default-object-access-controls".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("object-access-controls", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._object_access_controls_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._object_access_controls_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._object_access_controls_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._object_access_controls_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._object_access_controls_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._object_access_controls_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("object-access-controls".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("objects", Some(opt)) => { + match opt.subcommand() { + ("compose", Some(opt)) => { + call_result = self._objects_compose(opt, dry_run, &mut err); + }, + ("copy", Some(opt)) => { + call_result = self._objects_copy(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._objects_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._objects_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._objects_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._objects_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._objects_patch(opt, dry_run, &mut err); + }, + ("rewrite", Some(opt)) => { + call_result = self._objects_rewrite(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._objects_update(opt, dry_run, &mut err); + }, + ("watch-all", Some(opt)) => { + call_result = self._objects_watch_all(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("objects".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_buckets { - if self.opt.cmd_delete { - call_result = self._buckets_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._buckets_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._buckets_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._buckets_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._buckets_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._buckets_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_channels { - if self.opt.cmd_stop { - call_result = self._channels_stop(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_default_object_access_controls { - if self.opt.cmd_delete { - call_result = self._default_object_access_controls_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._default_object_access_controls_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._default_object_access_controls_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._default_object_access_controls_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._default_object_access_controls_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._default_object_access_controls_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_object_access_controls { - if self.opt.cmd_delete { - call_result = self._object_access_controls_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._object_access_controls_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._object_access_controls_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._object_access_controls_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._object_access_controls_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._object_access_controls_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_objects { - if self.opt.cmd_compose { - call_result = self._objects_compose(dry_run, &mut err); - } else if self.opt.cmd_copy { - call_result = self._objects_copy(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._objects_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._objects_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._objects_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._objects_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._objects_patch(dry_run, &mut err); - } else if self.opt.cmd_rewrite { - call_result = self._objects_rewrite(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._objects_update(dry_run, &mut err); - } else if self.opt.cmd_watch_all { - call_result = self._objects_watch_all(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -4052,7 +4186,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -4065,7 +4199,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -4075,37 +4209,1181 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Storage::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let upload_value_names = ["mode", "file"]; + let arg_data = [ + ("bucket-access-controls", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Permanently deletes the ACL entry for the specified entity on the specified bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/bucket-access-controls_delete", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"entity"##), + None, + Some(r##"The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Returns the ACL entry for the specified entity on the specified bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/bucket-access-controls_get", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"entity"##), + None, + Some(r##"The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new ACL entry on the specified bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/bucket-access-controls_insert", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves ACL entries on the specified bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/bucket-access-controls_list", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an ACL entry on the specified bucket. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/bucket-access-controls_patch", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"entity"##), + None, + Some(r##"The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an ACL entry on the specified bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/bucket-access-controls_update", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"entity"##), + None, + Some(r##"The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("buckets", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Permanently deletes an empty bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/buckets_delete", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Returns metadata for the specified bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/buckets_get", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/buckets_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"A valid API project identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of buckets for a given project."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/buckets_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"A valid API project identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a bucket. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/buckets_patch", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/buckets_update", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("channels", "methods: 'stop'", vec![ + ("stop", + Some(r##"Stop watching resources through this channel"##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/channels_stop", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("default-object-access-controls", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Permanently deletes the default object ACL entry for the specified entity on the specified bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/default-object-access-controls_delete", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"entity"##), + None, + Some(r##"The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Returns the default object ACL entry for the specified entity on the specified bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/default-object-access-controls_get", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"entity"##), + None, + Some(r##"The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new default object ACL entry on the specified bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/default-object-access-controls_insert", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves default object ACL entries on the specified bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/default-object-access-controls_list", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates a default object ACL entry on the specified bucket. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/default-object-access-controls_patch", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"entity"##), + None, + Some(r##"The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a default object ACL entry on the specified bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/default-object-access-controls_update", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"entity"##), + None, + Some(r##"The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("object-access-controls", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Permanently deletes the ACL entry for the specified entity on the specified object."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/object-access-controls_delete", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"object"##), + None, + Some(r##"Name of the object."##), + Some(true), + Some(false)), + + (Some(r##"entity"##), + None, + Some(r##"The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Returns the ACL entry for the specified entity on the specified object."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/object-access-controls_get", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"object"##), + None, + Some(r##"Name of the object."##), + Some(true), + Some(false)), + + (Some(r##"entity"##), + None, + Some(r##"The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new ACL entry on the specified object."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/object-access-controls_insert", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"object"##), + None, + Some(r##"Name of the object."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves ACL entries on the specified object."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/object-access-controls_list", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"object"##), + None, + Some(r##"Name of the object."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an ACL entry on the specified object. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/object-access-controls_patch", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"object"##), + None, + Some(r##"Name of the object."##), + Some(true), + Some(false)), + + (Some(r##"entity"##), + None, + Some(r##"The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an ACL entry on the specified object."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/object-access-controls_update", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of a bucket."##), + Some(true), + Some(false)), + + (Some(r##"object"##), + None, + Some(r##"Name of the object."##), + Some(true), + Some(false)), + + (Some(r##"entity"##), + None, + Some(r##"The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("objects", "methods: 'compose', 'copy', 'delete', 'get', 'insert', 'list', 'patch', 'rewrite', 'update' and 'watch-all'", vec![ + ("compose", + Some(r##"Concatenates a list of existing objects into a new object in the same bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/objects_compose", + vec![ + (Some(r##"destination-bucket"##), + None, + Some(r##"Name of the bucket in which to store the new object."##), + Some(true), + Some(false)), + + (Some(r##"destination-object"##), + None, + Some(r##"Name of the new object."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("copy", + Some(r##"Copies an object to a specified location. Optionally overrides metadata."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/objects_copy", + vec![ + (Some(r##"source-bucket"##), + None, + Some(r##"Name of the bucket in which to find the source object."##), + Some(true), + Some(false)), + + (Some(r##"source-object"##), + None, + Some(r##"Name of the source object."##), + Some(true), + Some(false)), + + (Some(r##"destination-bucket"##), + None, + Some(r##"Name of the bucket in which to store the new object. Overrides the provided object metadata's bucket value, if any."##), + Some(true), + Some(false)), + + (Some(r##"destination-object"##), + None, + Some(r##"Name of the new object. Required when the object metadata is not otherwise provided. Overrides the object metadata's name value, if any."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("delete", + Some(r##"Deletes an object and its metadata. Deletions are permanent if versioning is not enabled for the bucket, or if the generation parameter is used."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/objects_delete", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of the bucket in which the object resides."##), + Some(true), + Some(false)), + + (Some(r##"object"##), + None, + Some(r##"Name of the object."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves an object or its metadata."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/objects_get", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of the bucket in which the object resides."##), + Some(true), + Some(false)), + + (Some(r##"object"##), + None, + Some(r##"Name of the object."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Stores a new object and metadata."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/objects_insert", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of the bucket in which to store the new object. Overrides the provided object metadata's bucket value, if any."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of objects matching the criteria."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/objects_list", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of the bucket in which to look for objects."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates an object's metadata. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/objects_patch", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of the bucket in which the object resides."##), + Some(true), + Some(false)), + + (Some(r##"object"##), + None, + Some(r##"Name of the object."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("rewrite", + Some(r##"Rewrites a source object to a destination object. Optionally overrides metadata."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/objects_rewrite", + vec![ + (Some(r##"source-bucket"##), + None, + Some(r##"Name of the bucket in which to find the source object."##), + Some(true), + Some(false)), + + (Some(r##"source-object"##), + None, + Some(r##"Name of the source object."##), + Some(true), + Some(false)), + + (Some(r##"destination-bucket"##), + None, + Some(r##"Name of the bucket in which to store the new object. Overrides the provided object metadata's bucket value, if any."##), + Some(true), + Some(false)), + + (Some(r##"destination-object"##), + None, + Some(r##"Name of the new object. Required when the object metadata is not otherwise provided. Overrides the object metadata's name value, if any."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates an object's metadata."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/objects_update", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of the bucket in which the object resides."##), + Some(true), + Some(false)), + + (Some(r##"object"##), + None, + Some(r##"Name of the object."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("watch-all", + Some(r##"Watch for changes on all objects in a bucket."##), + "Details at http://byron.github.io/google-apis-rs/google_storage1_cli/objects_watch-all", + vec![ + (Some(r##"bucket"##), + None, + Some(r##"Name of the bucket in which to look for objects."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("storage1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150326") + .about("Lets you store and retrieve potentially-large, immutable data objects.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_storage1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + if arg_name_str == "mode" { + arg = arg.number_of_values(2); + arg = arg.value_names(&upload_value_names); + + scmd = scmd.arg(Arg::with_name("mime") + .short("m") + .requires("mode") + .required(false) + .help("The file's mime time, like 'application/octet-stream'") + .takes_value(true)); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/storage1/Cargo.toml b/gen/storage1/Cargo.toml index 7aeedba8f0..7b6ae31e78 100644 --- a/gen/storage1/Cargo.toml +++ b/gen/storage1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-storage1" -version = "0.1.6+20150326" +version = "0.1.7+20150326" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with storage (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/storage1" @@ -15,9 +15,10 @@ keywords = ["storage", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/storage1/README.md b/gen/storage1/README.md index c6e12dbf8b..d298717599 100644 --- a/gen/storage1/README.md +++ b/gen/storage1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-storage1` library allows access to all features of the *Google storage* service. -This documentation was generated from *storage* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *storage:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *storage* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *storage:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *storage* *v1* API can be found at the [official documentation site](https://developers.google.com/storage/docs/json_api/). @@ -212,7 +212,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_storage1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_storage1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/storage1/src/cmn.rs b/gen/storage1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/storage1/src/cmn.rs +++ b/gen/storage1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/storage1/src/lib.rs b/gen/storage1/src/lib.rs index d3ec828830..6491d420f6 100644 --- a/gen/storage1/src/lib.rs +++ b/gen/storage1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *storage* crate version *0.1.6+20150326*, where *20150326* is the exact revision of the *storage:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *storage* crate version *0.1.7+20150326*, where *20150326* is the exact revision of the *storage:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *storage* *v1* API can be found at the //! [official documentation site](https://developers.google.com/storage/docs/json_api/). @@ -213,7 +213,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -222,7 +222,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -238,6 +237,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -385,7 +385,7 @@ impl<'a, C, A> Storage<C, A> Storage { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -409,7 +409,7 @@ impl<'a, C, A> Storage<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -2230,6 +2230,7 @@ impl<'a, C, A> DefaultObjectAccessControlInsertCall<'a, C, A> where C: BorrowMut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ObjectAccessControl)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2285,11 +2286,20 @@ impl<'a, C, A> DefaultObjectAccessControlInsertCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2312,7 +2322,7 @@ impl<'a, C, A> DefaultObjectAccessControlInsertCall<'a, C, A> where C: BorrowMut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2494,6 +2504,7 @@ impl<'a, C, A> DefaultObjectAccessControlUpdateCall<'a, C, A> where C: BorrowMut /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ObjectAccessControl)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2550,11 +2561,20 @@ impl<'a, C, A> DefaultObjectAccessControlUpdateCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2577,7 +2597,7 @@ impl<'a, C, A> DefaultObjectAccessControlUpdateCall<'a, C, A> where C: BorrowMut request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2826,7 +2846,7 @@ impl<'a, C, A> DefaultObjectAccessControlListCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2848,7 +2868,7 @@ impl<'a, C, A> DefaultObjectAccessControlListCall<'a, C, A> where C: BorrowMut<h access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3032,6 +3052,7 @@ impl<'a, C, A> DefaultObjectAccessControlPatchCall<'a, C, A> where C: BorrowMut< /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ObjectAccessControl)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3088,11 +3109,20 @@ impl<'a, C, A> DefaultObjectAccessControlPatchCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3115,7 +3145,7 @@ impl<'a, C, A> DefaultObjectAccessControlPatchCall<'a, C, A> where C: BorrowMut< request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3355,7 +3385,7 @@ impl<'a, C, A> DefaultObjectAccessControlDeleteCall<'a, C, A> where C: BorrowMut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3377,7 +3407,7 @@ impl<'a, C, A> DefaultObjectAccessControlDeleteCall<'a, C, A> where C: BorrowMut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3596,7 +3626,7 @@ impl<'a, C, A> DefaultObjectAccessControlGetCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3618,7 +3648,7 @@ impl<'a, C, A> DefaultObjectAccessControlGetCall<'a, C, A> where C: BorrowMut<hy access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3798,6 +3828,7 @@ impl<'a, C, A> BucketAccessControlPatchCall<'a, C, A> where C: BorrowMut<hyper:: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, BucketAccessControl)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3854,11 +3885,20 @@ impl<'a, C, A> BucketAccessControlPatchCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3881,7 +3921,7 @@ impl<'a, C, A> BucketAccessControlPatchCall<'a, C, A> where C: BorrowMut<hyper:: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4121,7 +4161,7 @@ impl<'a, C, A> BucketAccessControlDeleteCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4143,7 +4183,7 @@ impl<'a, C, A> BucketAccessControlDeleteCall<'a, C, A> where C: BorrowMut<hyper: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4312,6 +4352,7 @@ impl<'a, C, A> BucketAccessControlInsertCall<'a, C, A> where C: BorrowMut<hyper: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, BucketAccessControl)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4367,11 +4408,20 @@ impl<'a, C, A> BucketAccessControlInsertCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4394,7 +4444,7 @@ impl<'a, C, A> BucketAccessControlInsertCall<'a, C, A> where C: BorrowMut<hyper: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4625,7 +4675,7 @@ impl<'a, C, A> BucketAccessControlGetCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4647,7 +4697,7 @@ impl<'a, C, A> BucketAccessControlGetCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4827,6 +4877,7 @@ impl<'a, C, A> BucketAccessControlUpdateCall<'a, C, A> where C: BorrowMut<hyper: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, BucketAccessControl)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4883,11 +4934,20 @@ impl<'a, C, A> BucketAccessControlUpdateCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4910,7 +4970,7 @@ impl<'a, C, A> BucketAccessControlUpdateCall<'a, C, A> where C: BorrowMut<hyper: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5149,7 +5209,7 @@ impl<'a, C, A> BucketAccessControlListCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5171,7 +5231,7 @@ impl<'a, C, A> BucketAccessControlListCall<'a, C, A> where C: BorrowMut<hyper::C access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5339,6 +5399,7 @@ impl<'a, C, A> ChannelStopCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5368,11 +5429,20 @@ impl<'a, C, A> ChannelStopCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5395,7 +5465,7 @@ impl<'a, C, A> ChannelStopCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5585,6 +5655,7 @@ impl<'a, C, A> ObjectRewriteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, RewriteResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5682,11 +5753,20 @@ impl<'a, C, A> ObjectRewriteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5709,7 +5789,7 @@ impl<'a, C, A> ObjectRewriteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6112,7 +6192,7 @@ impl<'a, C, A> ObjectGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6134,7 +6214,7 @@ impl<'a, C, A> ObjectGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6375,6 +6455,7 @@ impl<'a, C, A> ObjectUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Object)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6468,11 +6549,20 @@ impl<'a, C, A> ObjectUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6495,7 +6585,7 @@ impl<'a, C, A> ObjectUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6747,6 +6837,7 @@ impl<'a, C, A> ObjectWatchAllCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Channel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6820,11 +6911,20 @@ impl<'a, C, A> ObjectWatchAllCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6847,7 +6947,7 @@ impl<'a, C, A> ObjectWatchAllCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7093,6 +7193,7 @@ impl<'a, C, A> ObjectInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, Object)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7196,11 +7297,20 @@ impl<'a, C, A> ObjectInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7253,7 +7363,7 @@ impl<'a, C, A> ObjectInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: _ => (&mut request_value_reader as &mut io::Read, ContentType(json_mime_type.clone())), }; let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(content_type) @@ -7301,7 +7411,7 @@ impl<'a, C, A> ObjectInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: let upload_result = { let url_str = &res.headers.get::<Location>().expect("Location header is part of protocol").0; if upload_url_from_server { - dlg.store_upload_url(url_str); + dlg.store_upload_url(Some(url_str)); } cmn::ResumableUploadHelper { @@ -7329,6 +7439,7 @@ impl<'a, C, A> ObjectInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: Some(Ok(upload_result)) => { res = upload_result; if !res.status.is_success() { + dlg.store_upload_url(None); dlg.finished(false); return Err(Error::Failure(res)) } @@ -7574,6 +7685,7 @@ impl<'a, C, A> ObjectComposeCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Object)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7655,11 +7767,20 @@ impl<'a, C, A> ObjectComposeCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7682,7 +7803,7 @@ impl<'a, C, A> ObjectComposeCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7968,7 +8089,7 @@ impl<'a, C, A> ObjectDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7990,7 +8111,7 @@ impl<'a, C, A> ObjectDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8272,7 +8393,7 @@ impl<'a, C, A> ObjectListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8294,7 +8415,7 @@ impl<'a, C, A> ObjectListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8535,6 +8656,7 @@ impl<'a, C, A> ObjectCopyCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Object)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8642,11 +8764,20 @@ impl<'a, C, A> ObjectCopyCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8669,7 +8800,7 @@ impl<'a, C, A> ObjectCopyCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8972,6 +9103,7 @@ impl<'a, C, A> ObjectPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Object)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9049,11 +9181,20 @@ impl<'a, C, A> ObjectPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9076,7 +9217,7 @@ impl<'a, C, A> ObjectPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9319,6 +9460,7 @@ impl<'a, C, A> ObjectAccessControlInsertCall<'a, C, A> where C: BorrowMut<hyper: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ObjectAccessControl)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9378,11 +9520,20 @@ impl<'a, C, A> ObjectAccessControlInsertCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9405,7 +9556,7 @@ impl<'a, C, A> ObjectAccessControlInsertCall<'a, C, A> where C: BorrowMut<hyper: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9607,6 +9758,7 @@ impl<'a, C, A> ObjectAccessControlPatchCall<'a, C, A> where C: BorrowMut<hyper:: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ObjectAccessControl)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9667,11 +9819,20 @@ impl<'a, C, A> ObjectAccessControlPatchCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9694,7 +9855,7 @@ impl<'a, C, A> ObjectAccessControlPatchCall<'a, C, A> where C: BorrowMut<hyper:: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9957,7 +10118,7 @@ impl<'a, C, A> ObjectAccessControlListCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9979,7 +10140,7 @@ impl<'a, C, A> ObjectAccessControlListCall<'a, C, A> where C: BorrowMut<hyper::C access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10221,7 +10382,7 @@ impl<'a, C, A> ObjectAccessControlDeleteCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10243,7 +10404,7 @@ impl<'a, C, A> ObjectAccessControlDeleteCall<'a, C, A> where C: BorrowMut<hyper: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10486,7 +10647,7 @@ impl<'a, C, A> ObjectAccessControlGetCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10508,7 +10669,7 @@ impl<'a, C, A> ObjectAccessControlGetCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10708,6 +10869,7 @@ impl<'a, C, A> ObjectAccessControlUpdateCall<'a, C, A> where C: BorrowMut<hyper: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ObjectAccessControl)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10768,11 +10930,20 @@ impl<'a, C, A> ObjectAccessControlUpdateCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10795,7 +10966,7 @@ impl<'a, C, A> ObjectAccessControlUpdateCall<'a, C, A> where C: BorrowMut<hyper: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11013,6 +11184,7 @@ impl<'a, C, A> BucketUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Bucket)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11083,11 +11255,20 @@ impl<'a, C, A> BucketUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11110,7 +11291,7 @@ impl<'a, C, A> BucketUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11389,7 +11570,7 @@ impl<'a, C, A> BucketGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11411,7 +11592,7 @@ impl<'a, C, A> BucketGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11658,7 +11839,7 @@ impl<'a, C, A> BucketDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11680,7 +11861,7 @@ impl<'a, C, A> BucketDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11859,6 +12040,7 @@ impl<'a, C, A> BucketInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Bucket)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11899,11 +12081,20 @@ impl<'a, C, A> BucketInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11926,7 +12117,7 @@ impl<'a, C, A> BucketInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -12138,6 +12329,7 @@ impl<'a, C, A> BucketPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Bucket)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12208,11 +12400,20 @@ impl<'a, C, A> BucketPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12235,7 +12436,7 @@ impl<'a, C, A> BucketPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -12495,7 +12696,7 @@ impl<'a, C, A> BucketListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12517,7 +12718,7 @@ impl<'a, C, A> BucketListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/tagmanager1-cli/Cargo.toml b/gen/tagmanager1-cli/Cargo.toml index e484797a32..dc1bebb9d6 100644 --- a/gen/tagmanager1-cli/Cargo.toml +++ b/gen/tagmanager1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-tagmanager1-cli" -version = "0.1.0+20150121" +version = "0.2.0+20150121" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with Tag Manager (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/tagmanager1-cli" @@ -17,15 +17,14 @@ keywords = ["tagmanager", "google", "cli"] name = "tagmanager1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-tagmanager1] path = "../tagmanager1" diff --git a/gen/tagmanager1-cli/README.md b/gen/tagmanager1-cli/README.md index 3845151fc5..c04297137a 100644 --- a/gen/tagmanager1-cli/README.md +++ b/gen/tagmanager1-cli/README.md @@ -10,66 +10,68 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *Tag Manager* API can be found at the +[official documentation site](https://developers.google.com/tag-manager/api/v1/). + # Usage -This documentation was generated from the *Tag Manager* API at revision *20150121*. The CLI is at version *0.1.0*. +This documentation was generated from the *Tag Manager* API at revision *20150121*. The CLI is at version *0.2.0*. ```bash - tagmanager1 [options] accounts containers-create <account-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-delete <account-id> <container-id> [-p <v>...] - tagmanager1 [options] accounts containers-get <account-id> <container-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-list <account-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-macros-create <account-id> <container-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-macros-delete <account-id> <container-id> <macro-id> [-p <v>...] - tagmanager1 [options] accounts containers-macros-get <account-id> <container-id> <macro-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-macros-list <account-id> <container-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-macros-update <account-id> <container-id> <macro-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-rules-create <account-id> <container-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-rules-delete <account-id> <container-id> <rule-id> [-p <v>...] - tagmanager1 [options] accounts containers-rules-get <account-id> <container-id> <rule-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-rules-list <account-id> <container-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-rules-update <account-id> <container-id> <rule-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-tags-create <account-id> <container-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-tags-delete <account-id> <container-id> <tag-id> [-p <v>...] - tagmanager1 [options] accounts containers-tags-get <account-id> <container-id> <tag-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-tags-list <account-id> <container-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-tags-update <account-id> <container-id> <tag-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-triggers-create <account-id> <container-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-triggers-delete <account-id> <container-id> <trigger-id> [-p <v>...] - tagmanager1 [options] accounts containers-triggers-get <account-id> <container-id> <trigger-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-triggers-list <account-id> <container-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-triggers-update <account-id> <container-id> <trigger-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-update <account-id> <container-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-variables-create <account-id> <container-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-variables-delete <account-id> <container-id> <variable-id> [-p <v>...] - tagmanager1 [options] accounts containers-variables-get <account-id> <container-id> <variable-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-variables-list <account-id> <container-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-variables-update <account-id> <container-id> <variable-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-versions-create <account-id> <container-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-versions-delete <account-id> <container-id> <container-version-id> [-p <v>...] - tagmanager1 [options] accounts containers-versions-get <account-id> <container-id> <container-version-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-versions-list <account-id> <container-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-versions-publish <account-id> <container-id> <container-version-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-versions-restore <account-id> <container-id> <container-version-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-versions-undelete <account-id> <container-id> <container-version-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-versions-update <account-id> <container-id> <container-version-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts get <account-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts list [-p <v>...] [-o <out>] - tagmanager1 [options] accounts permissions-create <account-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts permissions-delete <account-id> <permission-id> [-p <v>...] - tagmanager1 [options] accounts permissions-get <account-id> <permission-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts permissions-list <account-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts permissions-update <account-id> <permission-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts update <account-id> -r <kv>... [-p <v>...] [-o <out>] +tagmanager1 [options] + accounts + containers-create <account-id> (-r <kv>)... [-p <v>]... [-o <out>] + containers-delete <account-id> <container-id> [-p <v>]... + containers-get <account-id> <container-id> [-p <v>]... [-o <out>] + containers-list <account-id> [-p <v>]... [-o <out>] + containers-macros-create <account-id> <container-id> (-r <kv>)... [-p <v>]... [-o <out>] + containers-macros-delete <account-id> <container-id> <macro-id> [-p <v>]... + containers-macros-get <account-id> <container-id> <macro-id> [-p <v>]... [-o <out>] + containers-macros-list <account-id> <container-id> [-p <v>]... [-o <out>] + containers-macros-update <account-id> <container-id> <macro-id> (-r <kv>)... [-p <v>]... [-o <out>] + containers-rules-create <account-id> <container-id> (-r <kv>)... [-p <v>]... [-o <out>] + containers-rules-delete <account-id> <container-id> <rule-id> [-p <v>]... + containers-rules-get <account-id> <container-id> <rule-id> [-p <v>]... [-o <out>] + containers-rules-list <account-id> <container-id> [-p <v>]... [-o <out>] + containers-rules-update <account-id> <container-id> <rule-id> (-r <kv>)... [-p <v>]... [-o <out>] + containers-tags-create <account-id> <container-id> (-r <kv>)... [-p <v>]... [-o <out>] + containers-tags-delete <account-id> <container-id> <tag-id> [-p <v>]... + containers-tags-get <account-id> <container-id> <tag-id> [-p <v>]... [-o <out>] + containers-tags-list <account-id> <container-id> [-p <v>]... [-o <out>] + containers-tags-update <account-id> <container-id> <tag-id> (-r <kv>)... [-p <v>]... [-o <out>] + containers-triggers-create <account-id> <container-id> (-r <kv>)... [-p <v>]... [-o <out>] + containers-triggers-delete <account-id> <container-id> <trigger-id> [-p <v>]... + containers-triggers-get <account-id> <container-id> <trigger-id> [-p <v>]... [-o <out>] + containers-triggers-list <account-id> <container-id> [-p <v>]... [-o <out>] + containers-triggers-update <account-id> <container-id> <trigger-id> (-r <kv>)... [-p <v>]... [-o <out>] + containers-update <account-id> <container-id> (-r <kv>)... [-p <v>]... [-o <out>] + containers-variables-create <account-id> <container-id> (-r <kv>)... [-p <v>]... [-o <out>] + containers-variables-delete <account-id> <container-id> <variable-id> [-p <v>]... + containers-variables-get <account-id> <container-id> <variable-id> [-p <v>]... [-o <out>] + containers-variables-list <account-id> <container-id> [-p <v>]... [-o <out>] + containers-variables-update <account-id> <container-id> <variable-id> (-r <kv>)... [-p <v>]... [-o <out>] + containers-versions-create <account-id> <container-id> (-r <kv>)... [-p <v>]... [-o <out>] + containers-versions-delete <account-id> <container-id> <container-version-id> [-p <v>]... + containers-versions-get <account-id> <container-id> <container-version-id> [-p <v>]... [-o <out>] + containers-versions-list <account-id> <container-id> [-p <v>]... [-o <out>] + containers-versions-publish <account-id> <container-id> <container-version-id> [-p <v>]... [-o <out>] + containers-versions-restore <account-id> <container-id> <container-version-id> [-p <v>]... [-o <out>] + containers-versions-undelete <account-id> <container-id> <container-version-id> [-p <v>]... [-o <out>] + containers-versions-update <account-id> <container-id> <container-version-id> (-r <kv>)... [-p <v>]... [-o <out>] + get <account-id> [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + permissions-create <account-id> (-r <kv>)... [-p <v>]... [-o <out>] + permissions-delete <account-id> <permission-id> [-p <v>]... + permissions-get <account-id> <permission-id> [-p <v>]... [-o <out>] + permissions-list <account-id> [-p <v>]... [-o <out>] + permissions-update <account-id> <permission-id> (-r <kv>)... [-p <v>]... [-o <out>] + update <account-id> (-r <kv>)... [-p <v>]... [-o <out>] tagmanager1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_tagmanager1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/tagmanager1-cli/mkdocs.yml b/gen/tagmanager1-cli/mkdocs.yml index ac7cda7588..0cd43595ef 100644 --- a/gen/tagmanager1-cli/mkdocs.yml +++ b/gen/tagmanager1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: Tag Manager v0.1.0+20150121 +site_name: Tag Manager v0.2.0+20150121 site_url: http://byron.github.io/google-apis-rs/google-tagmanager1-cli site_description: Write integrating applications with bcore diff --git a/gen/tagmanager1-cli/src/cmn.rs b/gen/tagmanager1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/tagmanager1-cli/src/cmn.rs +++ b/gen/tagmanager1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/tagmanager1-cli/src/main.rs b/gen/tagmanager1-cli/src/main.rs index c649ab231e..d3367ae597 100644 --- a/gen/tagmanager1-cli/src/main.rs +++ b/gen/tagmanager1-cli/src/main.rs @@ -2,114 +2,55 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_tagmanager1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - tagmanager1 [options] accounts containers-create <account-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-delete <account-id> <container-id> [-p <v>...] - tagmanager1 [options] accounts containers-get <account-id> <container-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-list <account-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-macros-create <account-id> <container-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-macros-delete <account-id> <container-id> <macro-id> [-p <v>...] - tagmanager1 [options] accounts containers-macros-get <account-id> <container-id> <macro-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-macros-list <account-id> <container-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-macros-update <account-id> <container-id> <macro-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-rules-create <account-id> <container-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-rules-delete <account-id> <container-id> <rule-id> [-p <v>...] - tagmanager1 [options] accounts containers-rules-get <account-id> <container-id> <rule-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-rules-list <account-id> <container-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-rules-update <account-id> <container-id> <rule-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-tags-create <account-id> <container-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-tags-delete <account-id> <container-id> <tag-id> [-p <v>...] - tagmanager1 [options] accounts containers-tags-get <account-id> <container-id> <tag-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-tags-list <account-id> <container-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-tags-update <account-id> <container-id> <tag-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-triggers-create <account-id> <container-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-triggers-delete <account-id> <container-id> <trigger-id> [-p <v>...] - tagmanager1 [options] accounts containers-triggers-get <account-id> <container-id> <trigger-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-triggers-list <account-id> <container-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-triggers-update <account-id> <container-id> <trigger-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-update <account-id> <container-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-variables-create <account-id> <container-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-variables-delete <account-id> <container-id> <variable-id> [-p <v>...] - tagmanager1 [options] accounts containers-variables-get <account-id> <container-id> <variable-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-variables-list <account-id> <container-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-variables-update <account-id> <container-id> <variable-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-versions-create <account-id> <container-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-versions-delete <account-id> <container-id> <container-version-id> [-p <v>...] - tagmanager1 [options] accounts containers-versions-get <account-id> <container-id> <container-version-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-versions-list <account-id> <container-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-versions-publish <account-id> <container-id> <container-version-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-versions-restore <account-id> <container-id> <container-version-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-versions-undelete <account-id> <container-id> <container-version-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts containers-versions-update <account-id> <container-id> <container-version-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts get <account-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts list [-p <v>...] [-o <out>] - tagmanager1 [options] accounts permissions-create <account-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts permissions-delete <account-id> <permission-id> [-p <v>...] - tagmanager1 [options] accounts permissions-get <account-id> <permission-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts permissions-list <account-id> [-p <v>...] [-o <out>] - tagmanager1 [options] accounts permissions-update <account-id> <permission-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 [options] accounts update <account-id> -r <kv>... [-p <v>...] [-o <out>] - tagmanager1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_tagmanager1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::TagManager<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _accounts_containers_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _accounts_containers_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Container::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -167,196 +108,208 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "container-id", "domain-name", "enabled-built-in-variable", "fingerprint", "name", "notes", "public-id", "time-zone-country-id", "time-zone-id", "usage-context"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().containers_create(request, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().containers_create(request, opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_delete(&self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _accounts_containers_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_get(&self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_macros_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_containers_macros_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Macro::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -411,196 +364,208 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "container-id", "disabling-rule-id", "enabling-rule-id", "fingerprint", "macro-id", "name", "notes", "schedule-end-ms", "schedule-start-ms", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().containers_macros_create(request, &self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().containers_macros_create(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_macros_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_macros_delete(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_macro_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_macros_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_macros_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("macro-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _accounts_containers_macros_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_macros_get(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_macro_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_macros_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_macros_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("macro-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_macros_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_macros_list(&self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_macros_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_macros_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_macros_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_containers_macros_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Macro::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -655,63 +620,68 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "container-id", "disabling-rule-id", "enabling-rule-id", "fingerprint", "macro-id", "name", "notes", "schedule-end-ms", "schedule-start-ms", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().containers_macros_update(request, &self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_macro_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().containers_macros_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("macro-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "fingerprint" => { call = call.fingerprint(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["fingerprint"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_rules_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_containers_rules_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Rule::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -745,196 +715,208 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "container-id", "fingerprint", "name", "notes", "rule-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().containers_rules_create(request, &self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().containers_rules_create(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_rules_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_rules_delete(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_rule_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_rules_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_rules_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("rule-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _accounts_containers_rules_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_rules_get(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_rule_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_rules_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_rules_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("rule-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_rules_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_rules_list(&self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_rules_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_rules_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_rules_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_containers_rules_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Rule::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -968,63 +950,68 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "container-id", "fingerprint", "name", "notes", "rule-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().containers_rules_update(request, &self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_rule_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().containers_rules_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("rule-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "fingerprint" => { call = call.fingerprint(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["fingerprint"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_tags_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_containers_tags_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Tag::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1120,196 +1107,208 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "blocking-rule-id", "blocking-trigger-id", "container-id", "fingerprint", "firing-rule-id", "firing-trigger-id", "key", "live-only", "name", "notes", "priority", "schedule-end-ms", "schedule-start-ms", "tag-id", "type", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().containers_tags_create(request, &self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().containers_tags_create(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_tags_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_tags_delete(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_tag_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_tags_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_tags_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("tag-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _accounts_containers_tags_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_tags_get(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_tag_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_tags_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_tags_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("tag-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_tags_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_tags_list(&self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_tags_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_tags_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_tags_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_containers_tags_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Tag::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1405,63 +1404,68 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "blocking-rule-id", "blocking-trigger-id", "container-id", "fingerprint", "firing-rule-id", "firing-trigger-id", "key", "live-only", "name", "notes", "priority", "schedule-end-ms", "schedule-start-ms", "tag-id", "type", "value"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().containers_tags_update(request, &self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_tag_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().containers_tags_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("tag-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "fingerprint" => { call = call.fingerprint(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["fingerprint"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_triggers_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_containers_triggers_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Trigger::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1663,196 +1667,208 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "check-validation", "container-id", "enable-all-videos", "event-name", "fingerprint", "interval", "key", "limit", "name", "trigger-id", "type", "unique-trigger-id", "value", "video-percentage-list", "wait-for-tags", "wait-for-tags-timeout"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().containers_triggers_create(request, &self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().containers_triggers_create(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_triggers_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_triggers_delete(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_trigger_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_triggers_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_triggers_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("trigger-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _accounts_containers_triggers_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_triggers_get(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_trigger_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_triggers_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_triggers_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("trigger-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_triggers_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_triggers_list(&self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_triggers_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_triggers_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_triggers_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_containers_triggers_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Trigger::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2054,63 +2070,68 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "check-validation", "container-id", "enable-all-videos", "event-name", "fingerprint", "interval", "key", "limit", "name", "trigger-id", "type", "unique-trigger-id", "value", "video-percentage-list", "wait-for-tags", "wait-for-tags-timeout"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().containers_triggers_update(request, &self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_trigger_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().containers_triggers_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("trigger-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "fingerprint" => { call = call.fingerprint(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["fingerprint"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_containers_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Container::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2168,63 +2189,68 @@ impl Engine { request.name = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "container-id", "domain-name", "enabled-built-in-variable", "fingerprint", "name", "notes", "public-id", "time-zone-country-id", "time-zone-id", "usage-context"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().containers_update(request, &self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().containers_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "fingerprint" => { call = call.fingerprint(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["fingerprint"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_variables_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_containers_variables_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Variable::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2279,196 +2305,208 @@ impl Engine { request.container_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "container-id", "disabling-trigger-id", "enabling-trigger-id", "fingerprint", "name", "notes", "schedule-end-ms", "schedule-start-ms", "type", "variable-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().containers_variables_create(request, &self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().containers_variables_create(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_variables_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_variables_delete(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_variable_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_variables_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_variables_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("variable-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _accounts_containers_variables_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_variables_get(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_variable_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_variables_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_variables_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("variable-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_variables_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_variables_list(&self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_variables_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_variables_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_variables_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_containers_variables_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Variable::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2523,63 +2561,68 @@ impl Engine { request.container_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "container-id", "disabling-trigger-id", "enabling-trigger-id", "fingerprint", "name", "notes", "schedule-end-ms", "schedule-start-ms", "type", "variable-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().containers_variables_update(request, &self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_variable_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().containers_variables_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("variable-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "fingerprint" => { call = call.fingerprint(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["fingerprint"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_versions_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_containers_versions_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::CreateContainerVersionRequestVersionOptions::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -2604,340 +2647,364 @@ impl Engine { request.quick_preview = Some(arg_from_str(value.unwrap_or("false"), err, "quick-preview", "boolean")); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["name", "notes", "quick-preview"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().containers_versions_create(request, &self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().containers_versions_create(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_versions_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_versions_delete(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_container_version_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_versions_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_versions_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("container-version-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _accounts_containers_versions_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_versions_get(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_container_version_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_versions_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_versions_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("container-version-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_versions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_versions_list(&self.opt.arg_account_id, &self.opt.arg_container_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_versions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_versions_list(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "headers" => { call = call.headers(arg_from_str(value.unwrap_or("false"), err, "headers", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["headers"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_versions_publish(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_versions_publish(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_container_version_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_versions_publish(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_versions_publish(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("container-version-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "fingerprint" => { call = call.fingerprint(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["fingerprint"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_versions_restore(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_versions_restore(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_container_version_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_versions_restore(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_versions_restore(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("container-version-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_versions_undelete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().containers_versions_undelete(&self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_container_version_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_containers_versions_undelete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().containers_versions_undelete(opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("container-version-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_containers_versions_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_containers_versions_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::ContainerVersion::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3040,155 +3107,168 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "container", "container-id", "container-version-id", "deleted", "domain-name", "enabled-built-in-variable", "fingerprint", "name", "notes", "public-id", "time-zone-country-id", "time-zone-id", "usage-context"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().containers_versions_update(request, &self.opt.arg_account_id, &self.opt.arg_container_id, &self.opt.arg_container_version_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().containers_versions_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("container-id").unwrap_or(""), opt.value_of("container-version-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "fingerprint" => { call = call.fingerprint(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["fingerprint"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().get(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().get(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.accounts().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_permissions_create(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_permissions_create(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UserAccess::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3229,196 +3309,208 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-access", "account-id", "email-address", "permission", "permission-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().permissions_create(request, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().permissions_create(request, opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_permissions_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().permissions_delete(&self.opt.arg_account_id, &self.opt.arg_permission_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_permissions_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().permissions_delete(opt.value_of("account-id").unwrap_or(""), opt.value_of("permission-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _accounts_permissions_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().permissions_get(&self.opt.arg_account_id, &self.opt.arg_permission_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_permissions_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().permissions_get(opt.value_of("account-id").unwrap_or(""), opt.value_of("permission-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_permissions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.accounts().permissions_list(&self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + fn _accounts_permissions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.accounts().permissions_list(opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_permissions_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_permissions_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::UserAccess::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3459,60 +3551,65 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-access", "account-id", "email-address", "permission", "permission-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().permissions_update(request, &self.opt.arg_account_id, &self.opt.arg_permission_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().permissions_update(request, opt.value_of("account-id").unwrap_or(""), opt.value_of("permission-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _accounts_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _accounts_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Account::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -3540,174 +3637,233 @@ impl Engine { request.account_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["account-id", "fingerprint", "name", "share-data"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.accounts().update(request, &self.opt.arg_account_id); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.accounts().update(request, opt.value_of("account-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "fingerprint" => { call = call.fingerprint(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["fingerprint"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_accounts { - if self.opt.cmd_containers_create { - call_result = self._accounts_containers_create(dry_run, &mut err); - } else if self.opt.cmd_containers_delete { - call_result = self._accounts_containers_delete(dry_run, &mut err); - } else if self.opt.cmd_containers_get { - call_result = self._accounts_containers_get(dry_run, &mut err); - } else if self.opt.cmd_containers_list { - call_result = self._accounts_containers_list(dry_run, &mut err); - } else if self.opt.cmd_containers_macros_create { - call_result = self._accounts_containers_macros_create(dry_run, &mut err); - } else if self.opt.cmd_containers_macros_delete { - call_result = self._accounts_containers_macros_delete(dry_run, &mut err); - } else if self.opt.cmd_containers_macros_get { - call_result = self._accounts_containers_macros_get(dry_run, &mut err); - } else if self.opt.cmd_containers_macros_list { - call_result = self._accounts_containers_macros_list(dry_run, &mut err); - } else if self.opt.cmd_containers_macros_update { - call_result = self._accounts_containers_macros_update(dry_run, &mut err); - } else if self.opt.cmd_containers_rules_create { - call_result = self._accounts_containers_rules_create(dry_run, &mut err); - } else if self.opt.cmd_containers_rules_delete { - call_result = self._accounts_containers_rules_delete(dry_run, &mut err); - } else if self.opt.cmd_containers_rules_get { - call_result = self._accounts_containers_rules_get(dry_run, &mut err); - } else if self.opt.cmd_containers_rules_list { - call_result = self._accounts_containers_rules_list(dry_run, &mut err); - } else if self.opt.cmd_containers_rules_update { - call_result = self._accounts_containers_rules_update(dry_run, &mut err); - } else if self.opt.cmd_containers_tags_create { - call_result = self._accounts_containers_tags_create(dry_run, &mut err); - } else if self.opt.cmd_containers_tags_delete { - call_result = self._accounts_containers_tags_delete(dry_run, &mut err); - } else if self.opt.cmd_containers_tags_get { - call_result = self._accounts_containers_tags_get(dry_run, &mut err); - } else if self.opt.cmd_containers_tags_list { - call_result = self._accounts_containers_tags_list(dry_run, &mut err); - } else if self.opt.cmd_containers_tags_update { - call_result = self._accounts_containers_tags_update(dry_run, &mut err); - } else if self.opt.cmd_containers_triggers_create { - call_result = self._accounts_containers_triggers_create(dry_run, &mut err); - } else if self.opt.cmd_containers_triggers_delete { - call_result = self._accounts_containers_triggers_delete(dry_run, &mut err); - } else if self.opt.cmd_containers_triggers_get { - call_result = self._accounts_containers_triggers_get(dry_run, &mut err); - } else if self.opt.cmd_containers_triggers_list { - call_result = self._accounts_containers_triggers_list(dry_run, &mut err); - } else if self.opt.cmd_containers_triggers_update { - call_result = self._accounts_containers_triggers_update(dry_run, &mut err); - } else if self.opt.cmd_containers_update { - call_result = self._accounts_containers_update(dry_run, &mut err); - } else if self.opt.cmd_containers_variables_create { - call_result = self._accounts_containers_variables_create(dry_run, &mut err); - } else if self.opt.cmd_containers_variables_delete { - call_result = self._accounts_containers_variables_delete(dry_run, &mut err); - } else if self.opt.cmd_containers_variables_get { - call_result = self._accounts_containers_variables_get(dry_run, &mut err); - } else if self.opt.cmd_containers_variables_list { - call_result = self._accounts_containers_variables_list(dry_run, &mut err); - } else if self.opt.cmd_containers_variables_update { - call_result = self._accounts_containers_variables_update(dry_run, &mut err); - } else if self.opt.cmd_containers_versions_create { - call_result = self._accounts_containers_versions_create(dry_run, &mut err); - } else if self.opt.cmd_containers_versions_delete { - call_result = self._accounts_containers_versions_delete(dry_run, &mut err); - } else if self.opt.cmd_containers_versions_get { - call_result = self._accounts_containers_versions_get(dry_run, &mut err); - } else if self.opt.cmd_containers_versions_list { - call_result = self._accounts_containers_versions_list(dry_run, &mut err); - } else if self.opt.cmd_containers_versions_publish { - call_result = self._accounts_containers_versions_publish(dry_run, &mut err); - } else if self.opt.cmd_containers_versions_restore { - call_result = self._accounts_containers_versions_restore(dry_run, &mut err); - } else if self.opt.cmd_containers_versions_undelete { - call_result = self._accounts_containers_versions_undelete(dry_run, &mut err); - } else if self.opt.cmd_containers_versions_update { - call_result = self._accounts_containers_versions_update(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._accounts_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._accounts_list(dry_run, &mut err); - } else if self.opt.cmd_permissions_create { - call_result = self._accounts_permissions_create(dry_run, &mut err); - } else if self.opt.cmd_permissions_delete { - call_result = self._accounts_permissions_delete(dry_run, &mut err); - } else if self.opt.cmd_permissions_get { - call_result = self._accounts_permissions_get(dry_run, &mut err); - } else if self.opt.cmd_permissions_list { - call_result = self._accounts_permissions_list(dry_run, &mut err); - } else if self.opt.cmd_permissions_update { - call_result = self._accounts_permissions_update(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._accounts_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("accounts", Some(opt)) => { + match opt.subcommand() { + ("containers-create", Some(opt)) => { + call_result = self._accounts_containers_create(opt, dry_run, &mut err); + }, + ("containers-delete", Some(opt)) => { + call_result = self._accounts_containers_delete(opt, dry_run, &mut err); + }, + ("containers-get", Some(opt)) => { + call_result = self._accounts_containers_get(opt, dry_run, &mut err); + }, + ("containers-list", Some(opt)) => { + call_result = self._accounts_containers_list(opt, dry_run, &mut err); + }, + ("containers-macros-create", Some(opt)) => { + call_result = self._accounts_containers_macros_create(opt, dry_run, &mut err); + }, + ("containers-macros-delete", Some(opt)) => { + call_result = self._accounts_containers_macros_delete(opt, dry_run, &mut err); + }, + ("containers-macros-get", Some(opt)) => { + call_result = self._accounts_containers_macros_get(opt, dry_run, &mut err); + }, + ("containers-macros-list", Some(opt)) => { + call_result = self._accounts_containers_macros_list(opt, dry_run, &mut err); + }, + ("containers-macros-update", Some(opt)) => { + call_result = self._accounts_containers_macros_update(opt, dry_run, &mut err); + }, + ("containers-rules-create", Some(opt)) => { + call_result = self._accounts_containers_rules_create(opt, dry_run, &mut err); + }, + ("containers-rules-delete", Some(opt)) => { + call_result = self._accounts_containers_rules_delete(opt, dry_run, &mut err); + }, + ("containers-rules-get", Some(opt)) => { + call_result = self._accounts_containers_rules_get(opt, dry_run, &mut err); + }, + ("containers-rules-list", Some(opt)) => { + call_result = self._accounts_containers_rules_list(opt, dry_run, &mut err); + }, + ("containers-rules-update", Some(opt)) => { + call_result = self._accounts_containers_rules_update(opt, dry_run, &mut err); + }, + ("containers-tags-create", Some(opt)) => { + call_result = self._accounts_containers_tags_create(opt, dry_run, &mut err); + }, + ("containers-tags-delete", Some(opt)) => { + call_result = self._accounts_containers_tags_delete(opt, dry_run, &mut err); + }, + ("containers-tags-get", Some(opt)) => { + call_result = self._accounts_containers_tags_get(opt, dry_run, &mut err); + }, + ("containers-tags-list", Some(opt)) => { + call_result = self._accounts_containers_tags_list(opt, dry_run, &mut err); + }, + ("containers-tags-update", Some(opt)) => { + call_result = self._accounts_containers_tags_update(opt, dry_run, &mut err); + }, + ("containers-triggers-create", Some(opt)) => { + call_result = self._accounts_containers_triggers_create(opt, dry_run, &mut err); + }, + ("containers-triggers-delete", Some(opt)) => { + call_result = self._accounts_containers_triggers_delete(opt, dry_run, &mut err); + }, + ("containers-triggers-get", Some(opt)) => { + call_result = self._accounts_containers_triggers_get(opt, dry_run, &mut err); + }, + ("containers-triggers-list", Some(opt)) => { + call_result = self._accounts_containers_triggers_list(opt, dry_run, &mut err); + }, + ("containers-triggers-update", Some(opt)) => { + call_result = self._accounts_containers_triggers_update(opt, dry_run, &mut err); + }, + ("containers-update", Some(opt)) => { + call_result = self._accounts_containers_update(opt, dry_run, &mut err); + }, + ("containers-variables-create", Some(opt)) => { + call_result = self._accounts_containers_variables_create(opt, dry_run, &mut err); + }, + ("containers-variables-delete", Some(opt)) => { + call_result = self._accounts_containers_variables_delete(opt, dry_run, &mut err); + }, + ("containers-variables-get", Some(opt)) => { + call_result = self._accounts_containers_variables_get(opt, dry_run, &mut err); + }, + ("containers-variables-list", Some(opt)) => { + call_result = self._accounts_containers_variables_list(opt, dry_run, &mut err); + }, + ("containers-variables-update", Some(opt)) => { + call_result = self._accounts_containers_variables_update(opt, dry_run, &mut err); + }, + ("containers-versions-create", Some(opt)) => { + call_result = self._accounts_containers_versions_create(opt, dry_run, &mut err); + }, + ("containers-versions-delete", Some(opt)) => { + call_result = self._accounts_containers_versions_delete(opt, dry_run, &mut err); + }, + ("containers-versions-get", Some(opt)) => { + call_result = self._accounts_containers_versions_get(opt, dry_run, &mut err); + }, + ("containers-versions-list", Some(opt)) => { + call_result = self._accounts_containers_versions_list(opt, dry_run, &mut err); + }, + ("containers-versions-publish", Some(opt)) => { + call_result = self._accounts_containers_versions_publish(opt, dry_run, &mut err); + }, + ("containers-versions-restore", Some(opt)) => { + call_result = self._accounts_containers_versions_restore(opt, dry_run, &mut err); + }, + ("containers-versions-undelete", Some(opt)) => { + call_result = self._accounts_containers_versions_undelete(opt, dry_run, &mut err); + }, + ("containers-versions-update", Some(opt)) => { + call_result = self._accounts_containers_versions_update(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._accounts_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._accounts_list(opt, dry_run, &mut err); + }, + ("permissions-create", Some(opt)) => { + call_result = self._accounts_permissions_create(opt, dry_run, &mut err); + }, + ("permissions-delete", Some(opt)) => { + call_result = self._accounts_permissions_delete(opt, dry_run, &mut err); + }, + ("permissions-get", Some(opt)) => { + call_result = self._accounts_permissions_get(opt, dry_run, &mut err); + }, + ("permissions-list", Some(opt)) => { + call_result = self._accounts_permissions_list(opt, dry_run, &mut err); + }, + ("permissions-update", Some(opt)) => { + call_result = self._accounts_permissions_update(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._accounts_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("accounts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -3720,7 +3876,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -3733,7 +3889,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -3743,37 +3899,1546 @@ impl Engine { let engine = Engine { opt: opt, hub: api::TagManager::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("accounts", "methods: 'containers-create', 'containers-delete', 'containers-get', 'containers-list', 'containers-macros-create', 'containers-macros-delete', 'containers-macros-get', 'containers-macros-list', 'containers-macros-update', 'containers-rules-create', 'containers-rules-delete', 'containers-rules-get', 'containers-rules-list', 'containers-rules-update', 'containers-tags-create', 'containers-tags-delete', 'containers-tags-get', 'containers-tags-list', 'containers-tags-update', 'containers-triggers-create', 'containers-triggers-delete', 'containers-triggers-get', 'containers-triggers-list', 'containers-triggers-update', 'containers-update', 'containers-variables-create', 'containers-variables-delete', 'containers-variables-get', 'containers-variables-list', 'containers-variables-update', 'containers-versions-create', 'containers-versions-delete', 'containers-versions-get', 'containers-versions-list', 'containers-versions-publish', 'containers-versions-restore', 'containers-versions-undelete', 'containers-versions-update', 'get', 'list', 'permissions-create', 'permissions-delete', 'permissions-get', 'permissions-list', 'permissions-update' and 'update'", vec![ + ("containers-create", + Some(r##"Creates a Container."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-create", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-delete", + Some(r##"Deletes a Container."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("containers-get", + Some(r##"Gets a Container."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-list", + Some(r##"Lists all Containers that belongs to a GTM Account."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-macros-create", + Some(r##"Creates a GTM Macro."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-macros-create", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-macros-delete", + Some(r##"Deletes a GTM Macro."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-macros-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"macro-id"##), + None, + Some(r##"The GTM Macro ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("containers-macros-get", + Some(r##"Gets a GTM Macro."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-macros-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"macro-id"##), + None, + Some(r##"The GTM Macro ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-macros-list", + Some(r##"Lists all GTM Macros of a Container."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-macros-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-macros-update", + Some(r##"Updates a GTM Macro."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-macros-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"macro-id"##), + None, + Some(r##"The GTM Macro ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-rules-create", + Some(r##"Creates a GTM Rule."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-rules-create", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-rules-delete", + Some(r##"Deletes a GTM Rule."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-rules-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"rule-id"##), + None, + Some(r##"The GTM Rule ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("containers-rules-get", + Some(r##"Gets a GTM Rule."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-rules-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"rule-id"##), + None, + Some(r##"The GTM Rule ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-rules-list", + Some(r##"Lists all GTM Rules of a Container."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-rules-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-rules-update", + Some(r##"Updates a GTM Rule."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-rules-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"rule-id"##), + None, + Some(r##"The GTM Rule ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-tags-create", + Some(r##"Creates a GTM Tag."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-tags-create", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-tags-delete", + Some(r##"Deletes a GTM Tag."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-tags-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"tag-id"##), + None, + Some(r##"The GTM Tag ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("containers-tags-get", + Some(r##"Gets a GTM Tag."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-tags-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"tag-id"##), + None, + Some(r##"The GTM Tag ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-tags-list", + Some(r##"Lists all GTM Tags of a Container."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-tags-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-tags-update", + Some(r##"Updates a GTM Tag."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-tags-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"tag-id"##), + None, + Some(r##"The GTM Tag ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-triggers-create", + Some(r##"Creates a GTM Trigger."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-triggers-create", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-triggers-delete", + Some(r##"Deletes a GTM Trigger."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-triggers-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"trigger-id"##), + None, + Some(r##"The GTM Trigger ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("containers-triggers-get", + Some(r##"Gets a GTM Trigger."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-triggers-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"trigger-id"##), + None, + Some(r##"The GTM Trigger ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-triggers-list", + Some(r##"Lists all GTM Triggers of a Container."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-triggers-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-triggers-update", + Some(r##"Updates a GTM Trigger."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-triggers-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"trigger-id"##), + None, + Some(r##"The GTM Trigger ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-update", + Some(r##"Updates a Container."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-variables-create", + Some(r##"Creates a GTM Variable."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-variables-create", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-variables-delete", + Some(r##"Deletes a GTM Variable."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-variables-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"variable-id"##), + None, + Some(r##"The GTM Variable ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("containers-variables-get", + Some(r##"Gets a GTM Variable."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-variables-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"variable-id"##), + None, + Some(r##"The GTM Variable ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-variables-list", + Some(r##"Lists all GTM Variables of a Container."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-variables-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-variables-update", + Some(r##"Updates a GTM Variable."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-variables-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"variable-id"##), + None, + Some(r##"The GTM Variable ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-versions-create", + Some(r##"Creates a Container Version."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-versions-create", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-versions-delete", + Some(r##"Deletes a Container Version."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-versions-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"container-version-id"##), + None, + Some(r##"The GTM Container Version ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("containers-versions-get", + Some(r##"Gets a Container Version."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-versions-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"container-version-id"##), + None, + Some(r##"The GTM Container Version ID. Specify published to retrieve the currently published version."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-versions-list", + Some(r##"Lists all Container Versions of a GTM Container."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-versions-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-versions-publish", + Some(r##"Publishes a Container Version."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-versions-publish", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"container-version-id"##), + None, + Some(r##"The GTM Container Version ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-versions-restore", + Some(r##"Restores a Container Version. This will overwrite the container's current configuration (including its macros, rules and tags). The operation will not have any effect on the version that is being served (i.e. the published version)."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-versions-restore", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"container-version-id"##), + None, + Some(r##"The GTM Container Version ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-versions-undelete", + Some(r##"Undeletes a Container Version."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-versions-undelete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"container-version-id"##), + None, + Some(r##"The GTM Container Version ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("containers-versions-update", + Some(r##"Updates a Container Version."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_containers-versions-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"container-id"##), + None, + Some(r##"The GTM Container ID."##), + Some(true), + Some(false)), + + (Some(r##"container-version-id"##), + None, + Some(r##"The GTM Container Version ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("get", + Some(r##"Gets a GTM Account."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists all GTM Accounts that a user has access to."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-create", + Some(r##"Creates a user's Account & Container Permissions."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_permissions-create", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-delete", + Some(r##"Removes a user from the account, revoking access to it and all of its containers."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_permissions-delete", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"permission-id"##), + None, + Some(r##"The GTM User ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("permissions-get", + Some(r##"Gets a user's Account & Container Permissions."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_permissions-get", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"permission-id"##), + None, + Some(r##"The GTM User ID."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-list", + Some(r##"List all users that have access to the account along with Account and Container Permissions granted to each of them."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_permissions-list", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID. @required tagmanager.accounts.permissions.list"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("permissions-update", + Some(r##"Updates a user's Account & Container Permissions."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_permissions-update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"permission-id"##), + None, + Some(r##"The GTM User ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates a GTM Account."##), + "Details at http://byron.github.io/google-apis-rs/google_tagmanager1_cli/accounts_update", + vec![ + (Some(r##"account-id"##), + None, + Some(r##"The GTM Account ID."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("tagmanager1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150121") + .about("API for accessing Tag Manager accounts and containers.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_tagmanager1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/tagmanager1/Cargo.toml b/gen/tagmanager1/Cargo.toml index 617a0c2250..426fe6c893 100644 --- a/gen/tagmanager1/Cargo.toml +++ b/gen/tagmanager1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-tagmanager1" -version = "0.1.6+20150121" +version = "0.1.7+20150121" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with Tag Manager (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/tagmanager1" @@ -15,9 +15,10 @@ keywords = ["tagmanager", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/tagmanager1/README.md b/gen/tagmanager1/README.md index e3ac82075b..82e8ceaec8 100644 --- a/gen/tagmanager1/README.md +++ b/gen/tagmanager1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-tagmanager1` library allows access to all features of the *Google Tag Manager* service. -This documentation was generated from *Tag Manager* crate version *0.1.6+20150121*, where *20150121* is the exact revision of the *tagmanager:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *Tag Manager* crate version *0.1.7+20150121*, where *20150121* is the exact revision of the *tagmanager:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *Tag Manager* *v1* API can be found at the [official documentation site](https://developers.google.com/tag-manager/api/v1/). @@ -209,7 +209,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_tagmanager1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_tagmanager1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/tagmanager1/src/cmn.rs b/gen/tagmanager1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/tagmanager1/src/cmn.rs +++ b/gen/tagmanager1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/tagmanager1/src/lib.rs b/gen/tagmanager1/src/lib.rs index c5bf297df5..9a33fa91e9 100644 --- a/gen/tagmanager1/src/lib.rs +++ b/gen/tagmanager1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *Tag Manager* crate version *0.1.6+20150121*, where *20150121* is the exact revision of the *tagmanager:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *Tag Manager* crate version *0.1.7+20150121*, where *20150121* is the exact revision of the *tagmanager:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *Tag Manager* *v1* API can be found at the //! [official documentation site](https://developers.google.com/tag-manager/api/v1/). @@ -210,7 +210,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -219,7 +219,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -235,6 +234,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -382,7 +382,7 @@ impl<'a, C, A> TagManager<C, A> TagManager { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -391,7 +391,7 @@ impl<'a, C, A> TagManager<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -2323,7 +2323,7 @@ impl<'a, C, A> AccountContainerListCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2345,7 +2345,7 @@ impl<'a, C, A> AccountContainerListCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2562,7 +2562,7 @@ impl<'a, C, A> AccountPermissionListCall<'a, C, A> where C: BorrowMut<hyper::Cli if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2584,7 +2584,7 @@ impl<'a, C, A> AccountPermissionListCall<'a, C, A> where C: BorrowMut<hyper::Cli access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2805,7 +2805,7 @@ impl<'a, C, A> AccountContainerVersionUndeleteCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2827,7 +2827,7 @@ impl<'a, C, A> AccountContainerVersionUndeleteCall<'a, C, A> where C: BorrowMut< access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3016,6 +3016,7 @@ impl<'a, C, A> AccountPermissionCreateCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, UserAccess)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3071,11 +3072,20 @@ impl<'a, C, A> AccountPermissionCreateCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3098,7 +3108,7 @@ impl<'a, C, A> AccountPermissionCreateCall<'a, C, A> where C: BorrowMut<hyper::C request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3328,7 +3338,7 @@ impl<'a, C, A> AccountPermissionDeleteCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3350,7 +3360,7 @@ impl<'a, C, A> AccountPermissionDeleteCall<'a, C, A> where C: BorrowMut<hyper::C access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3569,7 +3579,7 @@ impl<'a, C, A> AccountContainerGetCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3591,7 +3601,7 @@ impl<'a, C, A> AccountContainerGetCall<'a, C, A> where C: BorrowMut<hyper::Clien access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3825,7 +3835,7 @@ impl<'a, C, A> AccountContainerVersionListCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3847,7 +3857,7 @@ impl<'a, C, A> AccountContainerVersionListCall<'a, C, A> where C: BorrowMut<hype access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4037,6 +4047,7 @@ impl<'a, C, A> AccountContainerTriggerUpdateCall<'a, C, A> where C: BorrowMut<hy /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Trigger)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4097,11 +4108,20 @@ impl<'a, C, A> AccountContainerTriggerUpdateCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4124,7 +4144,7 @@ impl<'a, C, A> AccountContainerTriggerUpdateCall<'a, C, A> where C: BorrowMut<hy request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4384,7 +4404,7 @@ impl<'a, C, A> AccountContainerTriggerGetCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4406,7 +4426,7 @@ impl<'a, C, A> AccountContainerTriggerGetCall<'a, C, A> where C: BorrowMut<hyper access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4644,7 +4664,7 @@ impl<'a, C, A> AccountContainerDeleteCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4666,7 +4686,7 @@ impl<'a, C, A> AccountContainerDeleteCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -4835,6 +4855,7 @@ impl<'a, C, A> AccountContainerCreateCall<'a, C, A> where C: BorrowMut<hyper::Cl /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Container)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4890,11 +4911,20 @@ impl<'a, C, A> AccountContainerCreateCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4917,7 +4947,7 @@ impl<'a, C, A> AccountContainerCreateCall<'a, C, A> where C: BorrowMut<hyper::Cl request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5149,7 +5179,7 @@ impl<'a, C, A> AccountContainerTagDeleteCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5171,7 +5201,7 @@ impl<'a, C, A> AccountContainerTagDeleteCall<'a, C, A> where C: BorrowMut<hyper: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5354,6 +5384,7 @@ impl<'a, C, A> AccountContainerRuleUpdateCall<'a, C, A> where C: BorrowMut<hyper /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Rule)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -5414,11 +5445,20 @@ impl<'a, C, A> AccountContainerRuleUpdateCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -5441,7 +5481,7 @@ impl<'a, C, A> AccountContainerRuleUpdateCall<'a, C, A> where C: BorrowMut<hyper request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -5700,7 +5740,7 @@ impl<'a, C, A> AccountContainerRuleDeleteCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5722,7 +5762,7 @@ impl<'a, C, A> AccountContainerRuleDeleteCall<'a, C, A> where C: BorrowMut<hyper access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -5951,7 +5991,7 @@ impl<'a, C, A> AccountContainerTagListCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -5973,7 +6013,7 @@ impl<'a, C, A> AccountContainerTagListCall<'a, C, A> where C: BorrowMut<hyper::C access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6209,7 +6249,7 @@ impl<'a, C, A> AccountContainerVersionPublishCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6231,7 +6271,7 @@ impl<'a, C, A> AccountContainerVersionPublishCall<'a, C, A> where C: BorrowMut<h access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -6428,6 +6468,7 @@ impl<'a, C, A> AccountContainerTagCreateCall<'a, C, A> where C: BorrowMut<hyper: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Tag)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -6484,11 +6525,20 @@ impl<'a, C, A> AccountContainerTagCreateCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -6511,7 +6561,7 @@ impl<'a, C, A> AccountContainerTagCreateCall<'a, C, A> where C: BorrowMut<hyper: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -6752,7 +6802,7 @@ impl<'a, C, A> AccountContainerTriggerListCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -6774,7 +6824,7 @@ impl<'a, C, A> AccountContainerTriggerListCall<'a, C, A> where C: BorrowMut<hype access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7004,7 +7054,7 @@ impl<'a, C, A> AccountContainerVersionDeleteCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7026,7 +7076,7 @@ impl<'a, C, A> AccountContainerVersionDeleteCall<'a, C, A> where C: BorrowMut<hy access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7207,6 +7257,7 @@ impl<'a, C, A> AccountUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Account)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7265,11 +7316,20 @@ impl<'a, C, A> AccountUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7292,7 +7352,7 @@ impl<'a, C, A> AccountUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -7531,7 +7591,7 @@ impl<'a, C, A> AccountContainerMacroDeleteCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7553,7 +7613,7 @@ impl<'a, C, A> AccountContainerMacroDeleteCall<'a, C, A> where C: BorrowMut<hype access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -7733,6 +7793,7 @@ impl<'a, C, A> AccountContainerVersionCreateCall<'a, C, A> where C: BorrowMut<hy /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CreateContainerVersionResponse)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7789,11 +7850,20 @@ impl<'a, C, A> AccountContainerVersionCreateCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7816,7 +7886,7 @@ impl<'a, C, A> AccountContainerVersionCreateCall<'a, C, A> where C: BorrowMut<hy request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8057,7 +8127,7 @@ impl<'a, C, A> AccountPermissionGetCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8079,7 +8149,7 @@ impl<'a, C, A> AccountPermissionGetCall<'a, C, A> where C: BorrowMut<hyper::Clie access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8259,6 +8329,7 @@ impl<'a, C, A> AccountContainerRuleCreateCall<'a, C, A> where C: BorrowMut<hyper /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Rule)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8315,11 +8386,20 @@ impl<'a, C, A> AccountContainerRuleCreateCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8342,7 +8422,7 @@ impl<'a, C, A> AccountContainerRuleCreateCall<'a, C, A> where C: BorrowMut<hyper request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -8585,7 +8665,7 @@ impl<'a, C, A> AccountContainerVersionRestoreCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8607,7 +8687,7 @@ impl<'a, C, A> AccountContainerVersionRestoreCall<'a, C, A> where C: BorrowMut<h access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -8848,7 +8928,7 @@ impl<'a, C, A> AccountContainerRuleGetCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8870,7 +8950,7 @@ impl<'a, C, A> AccountContainerRuleGetCall<'a, C, A> where C: BorrowMut<hyper::C access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9060,6 +9140,7 @@ impl<'a, C, A> AccountContainerVariableCreateCall<'a, C, A> where C: BorrowMut<h /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Variable)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9116,11 +9197,20 @@ impl<'a, C, A> AccountContainerVariableCreateCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9143,7 +9233,7 @@ impl<'a, C, A> AccountContainerVariableCreateCall<'a, C, A> where C: BorrowMut<h request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9384,7 +9474,7 @@ impl<'a, C, A> AccountContainerVariableListCall<'a, C, A> where C: BorrowMut<hyp if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9406,7 +9496,7 @@ impl<'a, C, A> AccountContainerVariableListCall<'a, C, A> where C: BorrowMut<hyp access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -9586,6 +9676,7 @@ impl<'a, C, A> AccountContainerMacroCreateCall<'a, C, A> where C: BorrowMut<hype /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Macro)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9642,11 +9733,20 @@ impl<'a, C, A> AccountContainerMacroCreateCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9669,7 +9769,7 @@ impl<'a, C, A> AccountContainerMacroCreateCall<'a, C, A> where C: BorrowMut<hype request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -9912,7 +10012,7 @@ impl<'a, C, A> AccountContainerTagGetCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9934,7 +10034,7 @@ impl<'a, C, A> AccountContainerTagGetCall<'a, C, A> where C: BorrowMut<hyper::Cl access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10175,7 +10275,7 @@ impl<'a, C, A> AccountContainerVariableGetCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10197,7 +10297,7 @@ impl<'a, C, A> AccountContainerVariableGetCall<'a, C, A> where C: BorrowMut<hype access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10437,7 +10537,7 @@ impl<'a, C, A> AccountContainerTriggerDeleteCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10459,7 +10559,7 @@ impl<'a, C, A> AccountContainerTriggerDeleteCall<'a, C, A> where C: BorrowMut<hy access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10688,7 +10788,7 @@ impl<'a, C, A> AccountContainerMacroListCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10710,7 +10810,7 @@ impl<'a, C, A> AccountContainerMacroListCall<'a, C, A> where C: BorrowMut<hyper: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -10890,6 +10990,7 @@ impl<'a, C, A> AccountContainerTriggerCreateCall<'a, C, A> where C: BorrowMut<hy /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Trigger)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10946,11 +11047,20 @@ impl<'a, C, A> AccountContainerTriggerCreateCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10973,7 +11083,7 @@ impl<'a, C, A> AccountContainerTriggerCreateCall<'a, C, A> where C: BorrowMut<hy request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11168,6 +11278,7 @@ impl<'a, C, A> AccountContainerMacroUpdateCall<'a, C, A> where C: BorrowMut<hype /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Macro)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11228,11 +11339,20 @@ impl<'a, C, A> AccountContainerMacroUpdateCall<'a, C, A> where C: BorrowMut<hype if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11255,7 +11375,7 @@ impl<'a, C, A> AccountContainerMacroUpdateCall<'a, C, A> where C: BorrowMut<hype request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11485,7 +11605,7 @@ impl<'a, C, A> AccountListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11507,7 +11627,7 @@ impl<'a, C, A> AccountListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -11667,6 +11787,7 @@ impl<'a, C, A> AccountPermissionUpdateCall<'a, C, A> where C: BorrowMut<hyper::C /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, UserAccess)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -11723,11 +11844,20 @@ impl<'a, C, A> AccountPermissionUpdateCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -11750,7 +11880,7 @@ impl<'a, C, A> AccountPermissionUpdateCall<'a, C, A> where C: BorrowMut<hyper::C request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -11992,7 +12122,7 @@ impl<'a, C, A> AccountContainerVariableDeleteCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12014,7 +12144,7 @@ impl<'a, C, A> AccountContainerVariableDeleteCall<'a, C, A> where C: BorrowMut<h access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12241,7 +12371,7 @@ impl<'a, C, A> AccountGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12263,7 +12393,7 @@ impl<'a, C, A> AccountGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12435,6 +12565,7 @@ impl<'a, C, A> AccountContainerUpdateCall<'a, C, A> where C: BorrowMut<hyper::Cl /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Container)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12494,11 +12625,20 @@ impl<'a, C, A> AccountContainerUpdateCall<'a, C, A> where C: BorrowMut<hyper::Cl if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12521,7 +12661,7 @@ impl<'a, C, A> AccountContainerUpdateCall<'a, C, A> where C: BorrowMut<hyper::Cl request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -12769,7 +12909,7 @@ impl<'a, C, A> AccountContainerRuleListCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -12791,7 +12931,7 @@ impl<'a, C, A> AccountContainerRuleListCall<'a, C, A> where C: BorrowMut<hyper:: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -12974,6 +13114,7 @@ impl<'a, C, A> AccountContainerTagUpdateCall<'a, C, A> where C: BorrowMut<hyper: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Tag)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13034,11 +13175,20 @@ impl<'a, C, A> AccountContainerTagUpdateCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13061,7 +13211,7 @@ impl<'a, C, A> AccountContainerTagUpdateCall<'a, C, A> where C: BorrowMut<hyper: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -13321,7 +13471,7 @@ impl<'a, C, A> AccountContainerMacroGetCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13343,7 +13493,7 @@ impl<'a, C, A> AccountContainerMacroGetCall<'a, C, A> where C: BorrowMut<hyper:: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -13536,6 +13686,7 @@ impl<'a, C, A> AccountContainerVersionUpdateCall<'a, C, A> where C: BorrowMut<hy /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ContainerVersion)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13596,11 +13747,20 @@ impl<'a, C, A> AccountContainerVersionUpdateCall<'a, C, A> where C: BorrowMut<hy if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13623,7 +13783,7 @@ impl<'a, C, A> AccountContainerVersionUpdateCall<'a, C, A> where C: BorrowMut<hy request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -13835,6 +13995,7 @@ impl<'a, C, A> AccountContainerVariableUpdateCall<'a, C, A> where C: BorrowMut<h /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Variable)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -13895,11 +14056,20 @@ impl<'a, C, A> AccountContainerVariableUpdateCall<'a, C, A> where C: BorrowMut<h if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13922,7 +14092,7 @@ impl<'a, C, A> AccountContainerVariableUpdateCall<'a, C, A> where C: BorrowMut<h request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -14182,7 +14352,7 @@ impl<'a, C, A> AccountContainerVersionGetCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14204,7 +14374,7 @@ impl<'a, C, A> AccountContainerVersionGetCall<'a, C, A> where C: BorrowMut<hyper access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/taskqueue1_beta2-cli/Cargo.toml b/gen/taskqueue1_beta2-cli/Cargo.toml index f60db23222..19b1de128c 100644 --- a/gen/taskqueue1_beta2-cli/Cargo.toml +++ b/gen/taskqueue1_beta2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-taskqueue1_beta2-cli" -version = "0.1.0+20141111" +version = "0.2.0+20141111" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with taskqueue (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/taskqueue1_beta2-cli" @@ -17,15 +17,14 @@ keywords = ["taskqueue", "google", "cli"] name = "taskqueue1-beta2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-taskqueue1_beta2] path = "../taskqueue1_beta2" diff --git a/gen/taskqueue1_beta2-cli/README.md b/gen/taskqueue1_beta2-cli/README.md index c987877232..11bd9cd8c8 100644 --- a/gen/taskqueue1_beta2-cli/README.md +++ b/gen/taskqueue1_beta2-cli/README.md @@ -10,28 +10,31 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *taskqueue* API can be found at the +[official documentation site](https://developers.google.com/appengine/docs/python/taskqueue/rest). + # Usage -This documentation was generated from the *taskqueue* API at revision *20141111*. The CLI is at version *0.1.0*. +This documentation was generated from the *taskqueue* API at revision *20141111*. The CLI is at version *0.2.0*. ```bash - taskqueue1-beta2 [options] taskqueues get <project> <taskqueue> [-p <v>...] [-o <out>] - taskqueue1-beta2 [options] tasks delete <project> <taskqueue> <task> [-p <v>...] - taskqueue1-beta2 [options] tasks get <project> <taskqueue> <task> [-p <v>...] [-o <out>] - taskqueue1-beta2 [options] tasks insert <project> <taskqueue> -r <kv>... [-p <v>...] [-o <out>] - taskqueue1-beta2 [options] tasks lease <project> <taskqueue> <num-tasks> <lease-secs> [-p <v>...] [-o <out>] - taskqueue1-beta2 [options] tasks list <project> <taskqueue> [-p <v>...] [-o <out>] - taskqueue1-beta2 [options] tasks patch <project> <taskqueue> <task> <new-lease-seconds> -r <kv>... [-p <v>...] [-o <out>] - taskqueue1-beta2 [options] tasks update <project> <taskqueue> <task> <new-lease-seconds> -r <kv>... [-p <v>...] [-o <out>] +taskqueue1-beta2 [options] + taskqueues + get <project> <taskqueue> [-p <v>]... [-o <out>] + tasks + delete <project> <taskqueue> <task> [-p <v>]... + get <project> <taskqueue> <task> [-p <v>]... [-o <out>] + insert <project> <taskqueue> (-r <kv>)... [-p <v>]... [-o <out>] + lease <project> <taskqueue> <num-tasks> <lease-secs> [-p <v>]... [-o <out>] + list <project> <taskqueue> [-p <v>]... [-o <out>] + patch <project> <taskqueue> <task> <new-lease-seconds> (-r <kv>)... [-p <v>]... [-o <out>] + update <project> <taskqueue> <task> <new-lease-seconds> (-r <kv>)... [-p <v>]... [-o <out>] taskqueue1-beta2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_taskqueue1_beta2_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/taskqueue1_beta2-cli/mkdocs.yml b/gen/taskqueue1_beta2-cli/mkdocs.yml index 56925c90d3..5bc36c5381 100644 --- a/gen/taskqueue1_beta2-cli/mkdocs.yml +++ b/gen/taskqueue1_beta2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: taskqueue v0.1.0+20141111 +site_name: taskqueue v0.2.0+20141111 site_url: http://byron.github.io/google-apis-rs/google-taskqueue1_beta2-cli site_description: Write integrating applications with bcore diff --git a/gen/taskqueue1_beta2-cli/src/cmn.rs b/gen/taskqueue1_beta2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/taskqueue1_beta2-cli/src/cmn.rs +++ b/gen/taskqueue1_beta2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/taskqueue1_beta2-cli/src/main.rs b/gen/taskqueue1_beta2-cli/src/main.rs index 9a1adeb66c..efbc959ca6 100644 --- a/gen/taskqueue1_beta2-cli/src/main.rs +++ b/gen/taskqueue1_beta2-cli/src/main.rs @@ -2,215 +2,201 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_taskqueue1_beta2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - taskqueue1-beta2 [options] taskqueues get <project> <taskqueue> [-p <v>...] [-o <out>] - taskqueue1-beta2 [options] tasks delete <project> <taskqueue> <task> [-p <v>...] - taskqueue1-beta2 [options] tasks get <project> <taskqueue> <task> [-p <v>...] [-o <out>] - taskqueue1-beta2 [options] tasks insert <project> <taskqueue> -r <kv>... [-p <v>...] [-o <out>] - taskqueue1-beta2 [options] tasks lease <project> <taskqueue> <num-tasks> <lease-secs> [-p <v>...] [-o <out>] - taskqueue1-beta2 [options] tasks list <project> <taskqueue> [-p <v>...] [-o <out>] - taskqueue1-beta2 [options] tasks patch <project> <taskqueue> <task> <new-lease-seconds> -r <kv>... [-p <v>...] [-o <out>] - taskqueue1-beta2 [options] tasks update <project> <taskqueue> <task> <new-lease-seconds> -r <kv>... [-p <v>...] [-o <out>] - taskqueue1-beta2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_taskqueue1_beta2_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Taskqueue<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _taskqueues_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.taskqueues().get(&self.opt.arg_project, &self.opt.arg_taskqueue); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _taskqueues_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.taskqueues().get(opt.value_of("project").unwrap_or(""), opt.value_of("taskqueue").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "get-stats" => { call = call.get_stats(arg_from_str(value.unwrap_or("false"), err, "get-stats", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["get-stats"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasks_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tasks().delete(&self.opt.arg_project, &self.opt.arg_taskqueue, &self.opt.arg_task); - for parg in self.opt.arg_v.iter() { + fn _tasks_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tasks().delete(opt.value_of("project").unwrap_or(""), opt.value_of("taskqueue").unwrap_or(""), opt.value_of("task").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _tasks_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tasks().get(&self.opt.arg_project, &self.opt.arg_taskqueue, &self.opt.arg_task); - for parg in self.opt.arg_v.iter() { + fn _tasks_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tasks().get(opt.value_of("project").unwrap_or(""), opt.value_of("taskqueue").unwrap_or(""), opt.value_of("task").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasks_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tasks_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Task::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -250,60 +236,65 @@ impl Engine { request.enqueue_timestamp = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["enqueue-timestamp", "id", "kind", "lease-timestamp", "payload-base64", "queue-name", "retry-count", "tag"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tasks().insert(request, &self.opt.arg_project, &self.opt.arg_taskqueue); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tasks().insert(request, opt.value_of("project").unwrap_or(""), opt.value_of("taskqueue").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasks_lease(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let num_tasks: i32 = arg_from_str(&self.opt.arg_num_tasks, err, "<num-tasks>", "integer"); - let lease_secs: i32 = arg_from_str(&self.opt.arg_lease_secs, err, "<lease-secs>", "integer"); - let mut call = self.hub.tasks().lease(&self.opt.arg_project, &self.opt.arg_taskqueue, num_tasks, lease_secs); - for parg in self.opt.arg_v.iter() { + fn _tasks_lease(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let num_tasks: i32 = arg_from_str(&opt.value_of("num-tasks").unwrap_or(""), err, "<num-tasks>", "integer"); + let lease_secs: i32 = arg_from_str(&opt.value_of("lease-secs").unwrap_or(""), err, "<lease-secs>", "integer"); + let mut call = self.hub.tasks().lease(opt.value_of("project").unwrap_or(""), opt.value_of("taskqueue").unwrap_or(""), num_tasks, lease_secs); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "tag" => { @@ -312,98 +303,106 @@ impl Engine { "group-by-tag" => { call = call.group_by_tag(arg_from_str(value.unwrap_or("false"), err, "group-by-tag", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["group-by-tag", "tag"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasks_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tasks().list(&self.opt.arg_project, &self.opt.arg_taskqueue); - for parg in self.opt.arg_v.iter() { + fn _tasks_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tasks().list(opt.value_of("project").unwrap_or(""), opt.value_of("taskqueue").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasks_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tasks_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Task::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -443,61 +442,66 @@ impl Engine { request.enqueue_timestamp = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["enqueue-timestamp", "id", "kind", "lease-timestamp", "payload-base64", "queue-name", "retry-count", "tag"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let new_lease_seconds: i32 = arg_from_str(&self.opt.arg_new_lease_seconds, err, "<new-lease-seconds>", "integer"); - let mut call = self.hub.tasks().patch(request, &self.opt.arg_project, &self.opt.arg_taskqueue, &self.opt.arg_task, new_lease_seconds); - for parg in self.opt.arg_v.iter() { + let new_lease_seconds: i32 = arg_from_str(&opt.value_of("new-lease-seconds").unwrap_or(""), err, "<new-lease-seconds>", "integer"); + let mut call = self.hub.tasks().patch(request, opt.value_of("project").unwrap_or(""), opt.value_of("taskqueue").unwrap_or(""), opt.value_of("task").unwrap_or(""), new_lease_seconds); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasks_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tasks_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Task::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -537,101 +541,125 @@ impl Engine { request.enqueue_timestamp = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["enqueue-timestamp", "id", "kind", "lease-timestamp", "payload-base64", "queue-name", "retry-count", "tag"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let new_lease_seconds: i32 = arg_from_str(&self.opt.arg_new_lease_seconds, err, "<new-lease-seconds>", "integer"); - let mut call = self.hub.tasks().update(request, &self.opt.arg_project, &self.opt.arg_taskqueue, &self.opt.arg_task, new_lease_seconds); - for parg in self.opt.arg_v.iter() { + let new_lease_seconds: i32 = arg_from_str(&opt.value_of("new-lease-seconds").unwrap_or(""), err, "<new-lease-seconds>", "integer"); + let mut call = self.hub.tasks().update(request, opt.value_of("project").unwrap_or(""), opt.value_of("taskqueue").unwrap_or(""), opt.value_of("task").unwrap_or(""), new_lease_seconds); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_taskqueues { - if self.opt.cmd_get { - call_result = self._taskqueues_get(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("taskqueues", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._taskqueues_get(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("taskqueues".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("tasks", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._tasks_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._tasks_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._tasks_insert(opt, dry_run, &mut err); + }, + ("lease", Some(opt)) => { + call_result = self._tasks_lease(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._tasks_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._tasks_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._tasks_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("tasks".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_tasks { - if self.opt.cmd_delete { - call_result = self._tasks_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._tasks_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._tasks_insert(dry_run, &mut err); - } else if self.opt.cmd_lease { - call_result = self._tasks_lease(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._tasks_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._tasks_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._tasks_update(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -644,7 +672,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -657,7 +685,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -667,37 +695,413 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Taskqueue::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("taskqueues", "methods: 'get'", vec![ + ("get", + Some(r##"Get detailed information about a TaskQueue."##), + "Details at http://byron.github.io/google-apis-rs/google_taskqueue1_beta2_cli/taskqueues_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project under which the queue lies."##), + Some(true), + Some(false)), + + (Some(r##"taskqueue"##), + None, + Some(r##"The id of the taskqueue to get the properties of."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("tasks", "methods: 'delete', 'get', 'insert', 'lease', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Delete a task from a TaskQueue."##), + "Details at http://byron.github.io/google-apis-rs/google_taskqueue1_beta2_cli/tasks_delete", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project under which the queue lies."##), + Some(true), + Some(false)), + + (Some(r##"taskqueue"##), + None, + Some(r##"The taskqueue to delete a task from."##), + Some(true), + Some(false)), + + (Some(r##"task"##), + None, + Some(r##"The id of the task to delete."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Get a particular task from a TaskQueue."##), + "Details at http://byron.github.io/google-apis-rs/google_taskqueue1_beta2_cli/tasks_get", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project under which the queue lies."##), + Some(true), + Some(false)), + + (Some(r##"taskqueue"##), + None, + Some(r##"The taskqueue in which the task belongs."##), + Some(true), + Some(false)), + + (Some(r##"task"##), + None, + Some(r##"The task to get properties of."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Insert a new task in a TaskQueue"##), + "Details at http://byron.github.io/google-apis-rs/google_taskqueue1_beta2_cli/tasks_insert", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project under which the queue lies"##), + Some(true), + Some(false)), + + (Some(r##"taskqueue"##), + None, + Some(r##"The taskqueue to insert the task into"##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("lease", + Some(r##"Lease 1 or more tasks from a TaskQueue."##), + "Details at http://byron.github.io/google-apis-rs/google_taskqueue1_beta2_cli/tasks_lease", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project under which the queue lies."##), + Some(true), + Some(false)), + + (Some(r##"taskqueue"##), + None, + Some(r##"The taskqueue to lease a task from."##), + Some(true), + Some(false)), + + (Some(r##"num-tasks"##), + None, + Some(r##"The number of tasks to lease."##), + Some(true), + Some(false)), + + (Some(r##"lease-secs"##), + None, + Some(r##"The lease in seconds."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"List Tasks in a TaskQueue"##), + "Details at http://byron.github.io/google-apis-rs/google_taskqueue1_beta2_cli/tasks_list", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project under which the queue lies."##), + Some(true), + Some(false)), + + (Some(r##"taskqueue"##), + None, + Some(r##"The id of the taskqueue to list tasks from."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Update tasks that are leased out of a TaskQueue. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_taskqueue1_beta2_cli/tasks_patch", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project under which the queue lies."##), + Some(true), + Some(false)), + + (Some(r##"taskqueue"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"task"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"new-lease-seconds"##), + None, + Some(r##"The new lease in seconds."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Update tasks that are leased out of a TaskQueue."##), + "Details at http://byron.github.io/google-apis-rs/google_taskqueue1_beta2_cli/tasks_update", + vec![ + (Some(r##"project"##), + None, + Some(r##"The project under which the queue lies."##), + Some(true), + Some(false)), + + (Some(r##"taskqueue"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"task"##), + None, + None, + Some(true), + Some(false)), + + (Some(r##"new-lease-seconds"##), + None, + Some(r##"The new lease in seconds."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("taskqueue1-beta2") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20141111") + .about("Lets you access a Google App Engine Pull Task Queue over REST.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_taskqueue1_beta2_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/taskqueue1_beta2/Cargo.toml b/gen/taskqueue1_beta2/Cargo.toml index 228e9e8cf2..2dcb4b5765 100644 --- a/gen/taskqueue1_beta2/Cargo.toml +++ b/gen/taskqueue1_beta2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-taskqueue1_beta2" -version = "0.1.6+20141111" +version = "0.1.7+20141111" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with taskqueue (protocol v1beta2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/taskqueue1_beta2" @@ -15,9 +15,10 @@ keywords = ["taskqueue", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/taskqueue1_beta2/README.md b/gen/taskqueue1_beta2/README.md index e8a851b2dc..141a59ae2c 100644 --- a/gen/taskqueue1_beta2/README.md +++ b/gen/taskqueue1_beta2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-taskqueue1_beta2` library allows access to all features of the *Google taskqueue* service. -This documentation was generated from *taskqueue* crate version *0.1.6+20141111*, where *20141111* is the exact revision of the *taskqueue:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *taskqueue* crate version *0.1.7+20141111*, where *20141111* is the exact revision of the *taskqueue:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *taskqueue* *v1_beta2* API can be found at the [official documentation site](https://developers.google.com/appengine/docs/python/taskqueue/rest). @@ -167,7 +167,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_taskqueue1_beta2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_taskqueue1_beta2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/taskqueue1_beta2/src/cmn.rs b/gen/taskqueue1_beta2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/taskqueue1_beta2/src/cmn.rs +++ b/gen/taskqueue1_beta2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/taskqueue1_beta2/src/lib.rs b/gen/taskqueue1_beta2/src/lib.rs index 8a32519bdb..31fffdbd9b 100644 --- a/gen/taskqueue1_beta2/src/lib.rs +++ b/gen/taskqueue1_beta2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *taskqueue* crate version *0.1.6+20141111*, where *20141111* is the exact revision of the *taskqueue:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *taskqueue* crate version *0.1.7+20141111*, where *20141111* is the exact revision of the *taskqueue:v1beta2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *taskqueue* *v1_beta2* API can be found at the //! [official documentation site](https://developers.google.com/appengine/docs/python/taskqueue/rest). @@ -168,7 +168,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -177,7 +177,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -193,6 +192,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -315,7 +315,7 @@ impl<'a, C, A> Taskqueue<C, A> Taskqueue { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -327,7 +327,7 @@ impl<'a, C, A> Taskqueue<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -877,7 +877,7 @@ impl<'a, C, A> TaskqueueGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -899,7 +899,7 @@ impl<'a, C, A> TaskqueueGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1149,7 +1149,7 @@ impl<'a, C, A> TaskLeaseCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1171,7 +1171,7 @@ impl<'a, C, A> TaskLeaseCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1385,6 +1385,7 @@ impl<'a, C, A> TaskInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Task)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1441,11 +1442,20 @@ impl<'a, C, A> TaskInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1468,7 +1478,7 @@ impl<'a, C, A> TaskInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1710,7 +1720,7 @@ impl<'a, C, A> TaskDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1732,7 +1742,7 @@ impl<'a, C, A> TaskDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1914,6 +1924,7 @@ impl<'a, C, A> TaskPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Task)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1972,11 +1983,20 @@ impl<'a, C, A> TaskPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1999,7 +2019,7 @@ impl<'a, C, A> TaskPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2258,7 +2278,7 @@ impl<'a, C, A> TaskListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2280,7 +2300,7 @@ impl<'a, C, A> TaskListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2511,7 +2531,7 @@ impl<'a, C, A> TaskGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2533,7 +2553,7 @@ impl<'a, C, A> TaskGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2725,6 +2745,7 @@ impl<'a, C, A> TaskUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Task)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2783,11 +2804,20 @@ impl<'a, C, A> TaskUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2810,7 +2840,7 @@ impl<'a, C, A> TaskUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) diff --git a/gen/tasks1-cli/Cargo.toml b/gen/tasks1-cli/Cargo.toml index 244bc7da91..824b25ae96 100644 --- a/gen/tasks1-cli/Cargo.toml +++ b/gen/tasks1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-tasks1-cli" -version = "0.1.0+20141121" +version = "0.2.0+20141121" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with tasks (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/tasks1-cli" @@ -17,15 +17,14 @@ keywords = ["tasks", "google", "cli"] name = "tasks1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-tasks1] path = "../tasks1" diff --git a/gen/tasks1-cli/README.md b/gen/tasks1-cli/README.md index ab2a922f4f..12cf425cdd 100644 --- a/gen/tasks1-cli/README.md +++ b/gen/tasks1-cli/README.md @@ -10,34 +10,37 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *tasks* API can be found at the +[official documentation site](https://developers.google.com/google-apps/tasks/firstapp). + # Usage -This documentation was generated from the *tasks* API at revision *20141121*. The CLI is at version *0.1.0*. +This documentation was generated from the *tasks* API at revision *20141121*. The CLI is at version *0.2.0*. ```bash - tasks1 [options] tasklists delete <tasklist> [-p <v>...] - tasks1 [options] tasklists get <tasklist> [-p <v>...] [-o <out>] - tasks1 [options] tasklists insert -r <kv>... [-p <v>...] [-o <out>] - tasks1 [options] tasklists list [-p <v>...] [-o <out>] - tasks1 [options] tasklists patch <tasklist> -r <kv>... [-p <v>...] [-o <out>] - tasks1 [options] tasklists update <tasklist> -r <kv>... [-p <v>...] [-o <out>] - tasks1 [options] tasks clear <tasklist> [-p <v>...] - tasks1 [options] tasks delete <tasklist> <task> [-p <v>...] - tasks1 [options] tasks get <tasklist> <task> [-p <v>...] [-o <out>] - tasks1 [options] tasks insert <tasklist> -r <kv>... [-p <v>...] [-o <out>] - tasks1 [options] tasks list <tasklist> [-p <v>...] [-o <out>] - tasks1 [options] tasks move <tasklist> <task> [-p <v>...] [-o <out>] - tasks1 [options] tasks patch <tasklist> <task> -r <kv>... [-p <v>...] [-o <out>] - tasks1 [options] tasks update <tasklist> <task> -r <kv>... [-p <v>...] [-o <out>] +tasks1 [options] + tasklists + delete <tasklist> [-p <v>]... + get <tasklist> [-p <v>]... [-o <out>] + insert (-r <kv>)... [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + patch <tasklist> (-r <kv>)... [-p <v>]... [-o <out>] + update <tasklist> (-r <kv>)... [-p <v>]... [-o <out>] + tasks + clear <tasklist> [-p <v>]... + delete <tasklist> <task> [-p <v>]... + get <tasklist> <task> [-p <v>]... [-o <out>] + insert <tasklist> (-r <kv>)... [-p <v>]... [-o <out>] + list <tasklist> [-p <v>]... [-o <out>] + move <tasklist> <task> [-p <v>]... [-o <out>] + patch <tasklist> <task> (-r <kv>)... [-p <v>]... [-o <out>] + update <tasklist> <task> (-r <kv>)... [-p <v>]... [-o <out>] tasks1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_tasks1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/tasks1-cli/mkdocs.yml b/gen/tasks1-cli/mkdocs.yml index 416927b3ce..97d759a3ac 100644 --- a/gen/tasks1-cli/mkdocs.yml +++ b/gen/tasks1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: tasks v0.1.0+20141121 +site_name: tasks v0.2.0+20141121 site_url: http://byron.github.io/google-apis-rs/google-tasks1-cli site_description: Write integrating applications with bcore diff --git a/gen/tasks1-cli/src/cmn.rs b/gen/tasks1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/tasks1-cli/src/cmn.rs +++ b/gen/tasks1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/tasks1-cli/src/main.rs b/gen/tasks1-cli/src/main.rs index 2c767ed62e..6e9f5ce260 100644 --- a/gen/tasks1-cli/src/main.rs +++ b/gen/tasks1-cli/src/main.rs @@ -2,172 +2,148 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_tasks1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - tasks1 [options] tasklists delete <tasklist> [-p <v>...] - tasks1 [options] tasklists get <tasklist> [-p <v>...] [-o <out>] - tasks1 [options] tasklists insert -r <kv>... [-p <v>...] [-o <out>] - tasks1 [options] tasklists list [-p <v>...] [-o <out>] - tasks1 [options] tasklists patch <tasklist> -r <kv>... [-p <v>...] [-o <out>] - tasks1 [options] tasklists update <tasklist> -r <kv>... [-p <v>...] [-o <out>] - tasks1 [options] tasks clear <tasklist> [-p <v>...] - tasks1 [options] tasks delete <tasklist> <task> [-p <v>...] - tasks1 [options] tasks get <tasklist> <task> [-p <v>...] [-o <out>] - tasks1 [options] tasks insert <tasklist> -r <kv>... [-p <v>...] [-o <out>] - tasks1 [options] tasks list <tasklist> [-p <v>...] [-o <out>] - tasks1 [options] tasks move <tasklist> <task> [-p <v>...] [-o <out>] - tasks1 [options] tasks patch <tasklist> <task> -r <kv>... [-p <v>...] [-o <out>] - tasks1 [options] tasks update <tasklist> <task> -r <kv>... [-p <v>...] [-o <out>] - tasks1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_tasks1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::TasksHub<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _tasklists_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tasklists().delete(&self.opt.arg_tasklist); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _tasklists_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tasklists().delete(opt.value_of("tasklist").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _tasklists_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tasklists().get(&self.opt.arg_tasklist); - for parg in self.opt.arg_v.iter() { + fn _tasklists_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tasklists().get(opt.value_of("tasklist").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasklists_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tasklists_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TaskList::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -201,58 +177,63 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "id", "kind", "self-link", "title", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.tasklists().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasklists_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tasklists_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.tasklists().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "page-token" => { @@ -261,52 +242,56 @@ impl Engine { "max-results" => { call = call.max_results(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "max-results"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasklists_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tasklists_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TaskList::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -340,60 +325,65 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "id", "kind", "self-link", "title", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tasklists().patch(request, &self.opt.arg_tasklist); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tasklists().patch(request, opt.value_of("tasklist").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasklists_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tasklists_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::TaskList::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -427,194 +417,201 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "id", "kind", "self-link", "title", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tasklists().update(request, &self.opt.arg_tasklist); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tasklists().update(request, opt.value_of("tasklist").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasks_clear(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tasks().clear(&self.opt.arg_tasklist); - for parg in self.opt.arg_v.iter() { + fn _tasks_clear(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tasks().clear(opt.value_of("tasklist").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _tasks_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tasks().delete(&self.opt.arg_tasklist, &self.opt.arg_task); - for parg in self.opt.arg_v.iter() { + fn _tasks_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tasks().delete(opt.value_of("tasklist").unwrap_or(""), opt.value_of("task").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _tasks_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tasks().get(&self.opt.arg_tasklist, &self.opt.arg_task); - for parg in self.opt.arg_v.iter() { + fn _tasks_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tasks().get(opt.value_of("tasklist").unwrap_or(""), opt.value_of("task").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasks_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tasks_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Task::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -672,12 +669,13 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["completed", "deleted", "due", "etag", "hidden", "id", "kind", "notes", "parent", "position", "self-link", "status", "title", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tasks().insert(request, &self.opt.arg_tasklist); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tasks().insert(request, opt.value_of("tasklist").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "previous" => { @@ -686,50 +684,54 @@ impl Engine { "parent" => { call = call.parent(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["parent", "previous"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasks_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tasks().list(&self.opt.arg_tasklist); - for parg in self.opt.arg_v.iter() { + fn _tasks_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tasks().list(opt.value_of("tasklist").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "updated-min" => { @@ -762,50 +764,54 @@ impl Engine { "completed-max" => { call = call.completed_max(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["due-max", "show-deleted", "updated-min", "completed-min", "max-results", "show-completed", "page-token", "completed-max", "show-hidden", "due-min"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasks_move(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.tasks().move_(&self.opt.arg_tasklist, &self.opt.arg_task); - for parg in self.opt.arg_v.iter() { + fn _tasks_move(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.tasks().move_(opt.value_of("tasklist").unwrap_or(""), opt.value_of("task").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "previous" => { @@ -814,52 +820,56 @@ impl Engine { "parent" => { call = call.parent(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["parent", "previous"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasks_patch(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tasks_patch(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Task::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -917,60 +927,65 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["completed", "deleted", "due", "etag", "hidden", "id", "kind", "notes", "parent", "position", "self-link", "status", "title", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tasks().patch(request, &self.opt.arg_tasklist, &self.opt.arg_task); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tasks().patch(request, opt.value_of("tasklist").unwrap_or(""), opt.value_of("task").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _tasks_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _tasks_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Task::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -1028,112 +1043,142 @@ impl Engine { request.self_link = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["completed", "deleted", "due", "etag", "hidden", "id", "kind", "notes", "parent", "position", "self-link", "status", "title", "updated"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } - let mut call = self.hub.tasks().update(request, &self.opt.arg_tasklist, &self.opt.arg_task); - for parg in self.opt.arg_v.iter() { + let mut call = self.hub.tasks().update(request, opt.value_of("tasklist").unwrap_or(""), opt.value_of("task").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_tasklists { - if self.opt.cmd_delete { - call_result = self._tasklists_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._tasklists_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._tasklists_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._tasklists_list(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._tasklists_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._tasklists_update(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("tasklists", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._tasklists_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._tasklists_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._tasklists_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._tasklists_list(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._tasklists_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._tasklists_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("tasklists".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("tasks", Some(opt)) => { + match opt.subcommand() { + ("clear", Some(opt)) => { + call_result = self._tasks_clear(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._tasks_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._tasks_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._tasks_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._tasks_list(opt, dry_run, &mut err); + }, + ("move", Some(opt)) => { + call_result = self._tasks_move(opt, dry_run, &mut err); + }, + ("patch", Some(opt)) => { + call_result = self._tasks_patch(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._tasks_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("tasks".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_tasks { - if self.opt.cmd_clear { - call_result = self._tasks_clear(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._tasks_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._tasks_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._tasks_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._tasks_list(dry_run, &mut err); - } else if self.opt.cmd_move { - call_result = self._tasks_move(dry_run, &mut err); - } else if self.opt.cmd_patch { - call_result = self._tasks_patch(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._tasks_update(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -1146,7 +1191,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1159,7 +1204,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -1169,37 +1214,473 @@ impl Engine { let engine = Engine { opt: opt, hub: api::TasksHub::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("tasklists", "methods: 'delete', 'get', 'insert', 'list', 'patch' and 'update'", vec![ + ("delete", + Some(r##"Deletes the authenticated user's specified task list."##), + "Details at http://byron.github.io/google-apis-rs/google_tasks1_cli/tasklists_delete", + vec![ + (Some(r##"tasklist"##), + None, + Some(r##"Task list identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Returns the authenticated user's specified task list."##), + "Details at http://byron.github.io/google-apis-rs/google_tasks1_cli/tasklists_get", + vec![ + (Some(r##"tasklist"##), + None, + Some(r##"Task list identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new task list and adds it to the authenticated user's task lists."##), + "Details at http://byron.github.io/google-apis-rs/google_tasks1_cli/tasklists_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Returns all the authenticated user's task lists."##), + "Details at http://byron.github.io/google-apis-rs/google_tasks1_cli/tasklists_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates the authenticated user's specified task list. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_tasks1_cli/tasklists_patch", + vec![ + (Some(r##"tasklist"##), + None, + Some(r##"Task list identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates the authenticated user's specified task list."##), + "Details at http://byron.github.io/google-apis-rs/google_tasks1_cli/tasklists_update", + vec![ + (Some(r##"tasklist"##), + None, + Some(r##"Task list identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("tasks", "methods: 'clear', 'delete', 'get', 'insert', 'list', 'move', 'patch' and 'update'", vec![ + ("clear", + Some(r##"Clears all completed tasks from the specified task list. The affected tasks will be marked as 'hidden' and no longer be returned by default when retrieving all tasks for a task list."##), + "Details at http://byron.github.io/google-apis-rs/google_tasks1_cli/tasks_clear", + vec![ + (Some(r##"tasklist"##), + None, + Some(r##"Task list identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("delete", + Some(r##"Deletes the specified task from the task list."##), + "Details at http://byron.github.io/google-apis-rs/google_tasks1_cli/tasks_delete", + vec![ + (Some(r##"tasklist"##), + None, + Some(r##"Task list identifier."##), + Some(true), + Some(false)), + + (Some(r##"task"##), + None, + Some(r##"Task identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Returns the specified task."##), + "Details at http://byron.github.io/google-apis-rs/google_tasks1_cli/tasks_get", + vec![ + (Some(r##"tasklist"##), + None, + Some(r##"Task list identifier."##), + Some(true), + Some(false)), + + (Some(r##"task"##), + None, + Some(r##"Task identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new task on the specified task list."##), + "Details at http://byron.github.io/google-apis-rs/google_tasks1_cli/tasks_insert", + vec![ + (Some(r##"tasklist"##), + None, + Some(r##"Task list identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Returns all tasks in the specified task list."##), + "Details at http://byron.github.io/google-apis-rs/google_tasks1_cli/tasks_list", + vec![ + (Some(r##"tasklist"##), + None, + Some(r##"Task list identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("move", + Some(r##"Moves the specified task to another position in the task list. This can include putting it as a child task under a new parent and/or move it to a different position among its sibling tasks."##), + "Details at http://byron.github.io/google-apis-rs/google_tasks1_cli/tasks_move", + vec![ + (Some(r##"tasklist"##), + None, + Some(r##"Task list identifier."##), + Some(true), + Some(false)), + + (Some(r##"task"##), + None, + Some(r##"Task identifier."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("patch", + Some(r##"Updates the specified task. This method supports patch semantics."##), + "Details at http://byron.github.io/google-apis-rs/google_tasks1_cli/tasks_patch", + vec![ + (Some(r##"tasklist"##), + None, + Some(r##"Task list identifier."##), + Some(true), + Some(false)), + + (Some(r##"task"##), + None, + Some(r##"Task identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Updates the specified task."##), + "Details at http://byron.github.io/google-apis-rs/google_tasks1_cli/tasks_update", + vec![ + (Some(r##"tasklist"##), + None, + Some(r##"Task list identifier."##), + Some(true), + Some(false)), + + (Some(r##"task"##), + None, + Some(r##"Task identifier."##), + Some(true), + Some(false)), + + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("tasks1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20141121") + .about("Lets you manage your tasks and task lists.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_tasks1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/tasks1/Cargo.toml b/gen/tasks1/Cargo.toml index 1488653e1b..85c3328bb0 100644 --- a/gen/tasks1/Cargo.toml +++ b/gen/tasks1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-tasks1" -version = "0.1.6+20141121" +version = "0.1.7+20141121" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with tasks (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/tasks1" @@ -15,9 +15,10 @@ keywords = ["tasks", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/tasks1/README.md b/gen/tasks1/README.md index 448b71829c..80adffe035 100644 --- a/gen/tasks1/README.md +++ b/gen/tasks1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-tasks1` library allows access to all features of the *Google tasks* service. -This documentation was generated from *tasks* crate version *0.1.6+20141121*, where *20141121* is the exact revision of the *tasks:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *tasks* crate version *0.1.7+20141121*, where *20141121* is the exact revision of the *tasks:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *tasks* *v1* API can be found at the [official documentation site](https://developers.google.com/google-apps/tasks/firstapp). @@ -176,7 +176,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_tasks1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_tasks1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/tasks1/src/cmn.rs b/gen/tasks1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/tasks1/src/cmn.rs +++ b/gen/tasks1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/tasks1/src/lib.rs b/gen/tasks1/src/lib.rs index 31636d7f72..9931940e49 100644 --- a/gen/tasks1/src/lib.rs +++ b/gen/tasks1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *tasks* crate version *0.1.6+20141121*, where *20141121* is the exact revision of the *tasks:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *tasks* crate version *0.1.7+20141121*, where *20141121* is the exact revision of the *tasks:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *tasks* *v1* API can be found at the //! [official documentation site](https://developers.google.com/google-apps/tasks/firstapp). @@ -177,7 +177,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -186,7 +186,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -202,6 +201,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -332,7 +332,7 @@ impl<'a, C, A> TasksHub<C, A> TasksHub { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -344,7 +344,7 @@ impl<'a, C, A> TasksHub<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1031,7 +1031,7 @@ impl<'a, C, A> TaskListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1053,7 +1053,7 @@ impl<'a, C, A> TaskListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1293,6 +1293,7 @@ impl<'a, C, A> TaskUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Task)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1349,11 +1350,20 @@ impl<'a, C, A> TaskUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1376,7 +1386,7 @@ impl<'a, C, A> TaskUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1568,6 +1578,7 @@ impl<'a, C, A> TaskPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Task)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1624,11 +1635,20 @@ impl<'a, C, A> TaskPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1651,7 +1671,7 @@ impl<'a, C, A> TaskPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1889,7 +1909,7 @@ impl<'a, C, A> TaskClearCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1911,7 +1931,7 @@ impl<'a, C, A> TaskClearCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2130,7 +2150,7 @@ impl<'a, C, A> TaskMoveCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2152,7 +2172,7 @@ impl<'a, C, A> TaskMoveCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2394,7 +2414,7 @@ impl<'a, C, A> TaskDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2416,7 +2436,7 @@ impl<'a, C, A> TaskDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2635,7 +2655,7 @@ impl<'a, C, A> TaskGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2657,7 +2677,7 @@ impl<'a, C, A> TaskGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2840,6 +2860,7 @@ impl<'a, C, A> TaskInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Task)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2901,11 +2922,20 @@ impl<'a, C, A> TaskInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2928,7 +2958,7 @@ impl<'a, C, A> TaskInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3155,7 +3185,7 @@ impl<'a, C, A> TasklistListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3177,7 +3207,7 @@ impl<'a, C, A> TasklistListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3350,6 +3380,7 @@ impl<'a, C, A> TasklistUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, TaskList)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3405,11 +3436,20 @@ impl<'a, C, A> TasklistUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3432,7 +3472,7 @@ impl<'a, C, A> TasklistUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3660,7 +3700,7 @@ impl<'a, C, A> TasklistDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3682,7 +3722,7 @@ impl<'a, C, A> TasklistDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3841,6 +3881,7 @@ impl<'a, C, A> TasklistPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, TaskList)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3896,11 +3937,20 @@ impl<'a, C, A> TasklistPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3923,7 +3973,7 @@ impl<'a, C, A> TasklistPatchCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Patch, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Patch, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4103,6 +4153,7 @@ impl<'a, C, A> TasklistInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, TaskList)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -4133,11 +4184,20 @@ impl<'a, C, A> TasklistInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -4160,7 +4220,7 @@ impl<'a, C, A> TasklistInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -4379,7 +4439,7 @@ impl<'a, C, A> TasklistGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -4401,7 +4461,7 @@ impl<'a, C, A> TasklistGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/translate2-cli/Cargo.toml b/gen/translate2-cli/Cargo.toml index 11297d359e..ca768d61e6 100644 --- a/gen/translate2-cli/Cargo.toml +++ b/gen/translate2-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-translate2-cli" -version = "0.1.0+20141123" +version = "0.2.0+20141123" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with translate (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/translate2-cli" @@ -17,15 +17,14 @@ keywords = ["translate", "google", "cli"] name = "translate2" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-translate2] path = "../translate2" diff --git a/gen/translate2-cli/README.md b/gen/translate2-cli/README.md index a03562c420..63d0451437 100644 --- a/gen/translate2-cli/README.md +++ b/gen/translate2-cli/README.md @@ -10,19 +10,23 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *translate* API can be found at the +[official documentation site](https://developers.google.com/translate/v2/using_rest). + # Usage -This documentation was generated from the *translate* API at revision *20141123*. The CLI is at version *0.1.0*. +This documentation was generated from the *translate* API at revision *20141123*. The CLI is at version *0.2.0*. ```bash - translate2 [options] detections list <q>... [-p <v>...] [-o <out>] - translate2 [options] languages list [-p <v>...] [-o <out>] - translate2 [options] translations list <q>... <target> [-p <v>...] [-o <out>] +translate2 [options] + detections + list <q>... [-p <v>]... [-o <out>] + languages + list [-p <v>]... [-o <out>] + translations + list <q>... <target> [-p <v>]... [-o <out>] translate2 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_translate2_cli/index.html - Configuration: --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/translate2-cli/mkdocs.yml b/gen/translate2-cli/mkdocs.yml index 6892eb4424..b24880e921 100644 --- a/gen/translate2-cli/mkdocs.yml +++ b/gen/translate2-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: translate v0.1.0+20141123 +site_name: translate v0.2.0+20141123 site_url: http://byron.github.io/google-apis-rs/google-translate2-cli site_description: Write integrating applications with bcore diff --git a/gen/translate2-cli/src/cmn.rs b/gen/translate2-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/translate2-cli/src/cmn.rs +++ b/gen/translate2-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/translate2-cli/src/main.rs b/gen/translate2-cli/src/main.rs index c1e8e995f3..a93a65d21e 100644 --- a/gen/translate2-cli/src/main.rs +++ b/gen/translate2-cli/src/main.rs @@ -2,154 +2,150 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_translate2 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - translate2 [options] detections list <q>... [-p <v>...] [-o <out>] - translate2 [options] languages list [-p <v>...] [-o <out>] - translate2 [options] translations list <q>... <target> [-p <v>...] [-o <out>] - translate2 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_translate2_cli/index.html - -Configuration: - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Translate<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _detections_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.detections().list(&self.opt.arg_q); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _detections_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.detections().list(&opt.values_of("q").unwrap_or(Vec::new()).iter().map(|&v| v.to_string()).collect::<Vec<String>>()); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _languages_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _languages_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.languages().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "target" => { call = call.target(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["target"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _translations_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.translations().list(&self.opt.arg_q, &self.opt.arg_target); - for parg in self.opt.arg_v.iter() { + fn _translations_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.translations().list(&opt.values_of("q").unwrap_or(Vec::new()).iter().map(|&v| v.to_string()).collect::<Vec<String>>(), opt.value_of("target").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "source" => { @@ -161,84 +157,105 @@ impl Engine { "cid" => { call = call.add_cid(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["source", "cid", "format"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_detections { - if self.opt.cmd_list { - call_result = self._detections_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("detections", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._detections_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("detections".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("languages", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._languages_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("languages".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("translations", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._translations_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("translations".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_languages { - if self.opt.cmd_list { - call_result = self._languages_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_translations { - if self.opt.cmd_list { - call_result = self._translations_list(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -251,7 +268,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -264,7 +281,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -274,37 +291,193 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Translate::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("detections", "methods: 'list'", vec![ + ("list", + Some(r##"Detect the language of text."##), + "Details at http://byron.github.io/google-apis-rs/google_translate2_cli/detections_list", + vec![ + (Some(r##"q"##), + None, + Some(r##"The text to detect"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("languages", "methods: 'list'", vec![ + ("list", + Some(r##"List the source/target languages supported by the API"##), + "Details at http://byron.github.io/google-apis-rs/google_translate2_cli/languages_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("translations", "methods: 'list'", vec![ + ("list", + Some(r##"Returns text translations from one language to another."##), + "Details at http://byron.github.io/google-apis-rs/google_translate2_cli/translations_list", + vec![ + (Some(r##"q"##), + None, + Some(r##"The text to translate"##), + Some(true), + Some(false)), + + (Some(r##"target"##), + None, + Some(r##"The target language into which the text should be translated"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("translate2") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20141123") + .about("Lets you translate text from one language to another") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_translate2_cli") + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/translate2/Cargo.toml b/gen/translate2/Cargo.toml index f7747801f2..ffbeb75a44 100644 --- a/gen/translate2/Cargo.toml +++ b/gen/translate2/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-translate2" -version = "0.1.6+20141123" +version = "0.1.7+20141123" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with translate (protocol v2)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/translate2" @@ -15,9 +15,10 @@ keywords = ["translate", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/translate2/README.md b/gen/translate2/README.md index 9c33cf73ec..dceed7a5f2 100644 --- a/gen/translate2/README.md +++ b/gen/translate2/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-translate2` library allows access to all features of the *Google translate* service. -This documentation was generated from *translate* crate version *0.1.6+20141123*, where *20141123* is the exact revision of the *translate:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *translate* crate version *0.1.7+20141123*, where *20141123* is the exact revision of the *translate:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *translate* *v2* API can be found at the [official documentation site](https://developers.google.com/translate/v2/using_rest). @@ -161,7 +161,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_translate2/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_translate2/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/translate2/src/cmn.rs b/gen/translate2/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/translate2/src/cmn.rs +++ b/gen/translate2/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/translate2/src/lib.rs b/gen/translate2/src/lib.rs index ef92eeb6e6..779d2580d4 100644 --- a/gen/translate2/src/lib.rs +++ b/gen/translate2/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *translate* crate version *0.1.6+20141123*, where *20141123* is the exact revision of the *translate:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *translate* crate version *0.1.7+20141123*, where *20141123* is the exact revision of the *translate:v2* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *translate* *v2* API can be found at the //! [official documentation site](https://developers.google.com/translate/v2/using_rest). @@ -162,7 +162,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -171,7 +171,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -187,6 +186,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -281,7 +281,7 @@ impl<'a, C, A> Translate<C, A> Translate { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -296,7 +296,7 @@ impl<'a, C, A> Translate<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -707,7 +707,7 @@ impl<'a, C, A> LanguageListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -715,7 +715,7 @@ impl<'a, C, A> LanguageListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -902,7 +902,7 @@ impl<'a, C, A> DetectionListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -910,7 +910,7 @@ impl<'a, C, A> DetectionListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); @@ -1122,7 +1122,7 @@ impl<'a, C, A> TranslationListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1130,7 +1130,7 @@ impl<'a, C, A> TranslationListCall<'a, C, A> where C: BorrowMut<hyper::Client>, loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); diff --git a/gen/urlshortener1-cli/Cargo.toml b/gen/urlshortener1-cli/Cargo.toml index 7ebbf1ab90..cb5c1cd5c4 100644 --- a/gen/urlshortener1-cli/Cargo.toml +++ b/gen/urlshortener1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-urlshortener1-cli" -version = "0.1.0+20150319" +version = "0.2.0+20150319" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with urlshortener (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/urlshortener1-cli" @@ -17,15 +17,14 @@ keywords = ["urlshortener", "google", "cli"] name = "urlshortener1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-urlshortener1] path = "../urlshortener1" diff --git a/gen/urlshortener1-cli/README.md b/gen/urlshortener1-cli/README.md index 4b00239289..cc57aa618c 100644 --- a/gen/urlshortener1-cli/README.md +++ b/gen/urlshortener1-cli/README.md @@ -10,23 +10,25 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *urlshortener* API can be found at the +[official documentation site](https://developers.google.com/url-shortener/v1/getting_started). + # Usage -This documentation was generated from the *urlshortener* API at revision *20150319*. The CLI is at version *0.1.0*. +This documentation was generated from the *urlshortener* API at revision *20150319*. The CLI is at version *0.2.0*. ```bash - urlshortener1 [options] url get <short-url> [-p <v>...] [-o <out>] - urlshortener1 [options] url insert -r <kv>... [-p <v>...] [-o <out>] - urlshortener1 [options] url list [-p <v>...] [-o <out>] +urlshortener1 [options] + url + get <short-url> [-p <v>]... [-o <out>] + insert (-r <kv>)... [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] urlshortener1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_urlshortener1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/urlshortener1-cli/mkdocs.yml b/gen/urlshortener1-cli/mkdocs.yml index 164989dafb..5e7fc995bb 100644 --- a/gen/urlshortener1-cli/mkdocs.yml +++ b/gen/urlshortener1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: urlshortener v0.1.0+20150319 +site_name: urlshortener v0.2.0+20150319 site_url: http://byron.github.io/google-apis-rs/google-urlshortener1-cli site_description: Write integrating applications with bcore diff --git a/gen/urlshortener1-cli/src/cmn.rs b/gen/urlshortener1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/urlshortener1-cli/src/cmn.rs +++ b/gen/urlshortener1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/urlshortener1-cli/src/main.rs b/gen/urlshortener1-cli/src/main.rs index c85f416222..430df55317 100644 --- a/gen/urlshortener1-cli/src/main.rs +++ b/gen/urlshortener1-cli/src/main.rs @@ -2,120 +2,108 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_urlshortener1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - urlshortener1 [options] url get <short-url> [-p <v>...] [-o <out>] - urlshortener1 [options] url insert -r <kv>... [-p <v>...] [-o <out>] - urlshortener1 [options] url list [-p <v>...] [-o <out>] - urlshortener1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_urlshortener1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Urlshortener<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _url_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.url().get(&self.opt.arg_short_url); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _url_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.url().get(opt.value_of("short-url").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "projection" => { call = call.projection(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["projection"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _url_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _url_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Url::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -229,58 +217,63 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["all-time", "analytics", "created", "day", "id", "kind", "long-url", "long-url-clicks", "month", "short-url-clicks", "status", "two-hours", "week"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.url().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _url_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _url_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.url().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-token" => { @@ -289,77 +282,92 @@ impl Engine { "projection" => { call = call.projection(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["start-token", "projection"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_url { - if self.opt.cmd_get { - call_result = self._url_get(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._url_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._url_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("url", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._url_get(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._url_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._url_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("url".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -372,7 +380,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -385,7 +393,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -395,37 +403,186 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Urlshortener::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("url", "methods: 'get', 'insert' and 'list'", vec![ + ("get", + Some(r##"Expands a short URL or gets creation time and analytics."##), + "Details at http://byron.github.io/google-apis-rs/google_urlshortener1_cli/url_get", + vec![ + (Some(r##"short-url"##), + None, + Some(r##"The short URL, including the protocol."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("insert", + Some(r##"Creates a new short URL."##), + "Details at http://byron.github.io/google-apis-rs/google_urlshortener1_cli/url_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Retrieves a list of URLs shortened by a user."##), + "Details at http://byron.github.io/google-apis-rs/google_urlshortener1_cli/url_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("urlshortener1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150319") + .about("Lets you create, inspect, and manage goo.gl short URLs") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_urlshortener1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/urlshortener1/Cargo.toml b/gen/urlshortener1/Cargo.toml index a7df426000..3804ae9fff 100644 --- a/gen/urlshortener1/Cargo.toml +++ b/gen/urlshortener1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-urlshortener1" -version = "0.1.6+20150319" +version = "0.1.7+20150319" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with urlshortener (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/urlshortener1" @@ -15,9 +15,10 @@ keywords = ["urlshortener", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/urlshortener1/README.md b/gen/urlshortener1/README.md index b841bbfb86..deb945cf2b 100644 --- a/gen/urlshortener1/README.md +++ b/gen/urlshortener1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-urlshortener1` library allows access to all features of the *Google urlshortener* service. -This documentation was generated from *urlshortener* crate version *0.1.6+20150319*, where *20150319* is the exact revision of the *urlshortener:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *urlshortener* crate version *0.1.7+20150319*, where *20150319* is the exact revision of the *urlshortener:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *urlshortener* *v1* API can be found at the [official documentation site](https://developers.google.com/url-shortener/v1/getting_started). @@ -159,7 +159,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_urlshortener1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_urlshortener1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/urlshortener1/src/cmn.rs b/gen/urlshortener1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/urlshortener1/src/cmn.rs +++ b/gen/urlshortener1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/urlshortener1/src/lib.rs b/gen/urlshortener1/src/lib.rs index c5de748143..f912cd66ea 100644 --- a/gen/urlshortener1/src/lib.rs +++ b/gen/urlshortener1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *urlshortener* crate version *0.1.6+20150319*, where *20150319* is the exact revision of the *urlshortener:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *urlshortener* crate version *0.1.7+20150319*, where *20150319* is the exact revision of the *urlshortener:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *urlshortener* *v1* API can be found at the //! [official documentation site](https://developers.google.com/url-shortener/v1/getting_started). @@ -160,7 +160,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -169,7 +169,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -185,6 +184,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -302,7 +302,7 @@ impl<'a, C, A> Urlshortener<C, A> Urlshortener { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -311,7 +311,7 @@ impl<'a, C, A> Urlshortener<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -602,6 +602,7 @@ impl<'a, C, A> UrlInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Url)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -632,11 +633,20 @@ impl<'a, C, A> UrlInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -659,7 +669,7 @@ impl<'a, C, A> UrlInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -859,7 +869,7 @@ impl<'a, C, A> UrlGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth2 if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -881,7 +891,7 @@ impl<'a, C, A> UrlGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth2 access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1089,7 +1099,7 @@ impl<'a, C, A> UrlListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1111,7 +1121,7 @@ impl<'a, C, A> UrlListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/webfonts1-cli/Cargo.toml b/gen/webfonts1-cli/Cargo.toml index 69c03e8f27..e76c3f056f 100644 --- a/gen/webfonts1-cli/Cargo.toml +++ b/gen/webfonts1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-webfonts1-cli" -version = "0.1.0+20140210" +version = "0.2.0+20140210" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with webfonts (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/webfonts1-cli" @@ -17,15 +17,14 @@ keywords = ["webfonts", "google", "cli"] name = "webfonts1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-webfonts1] path = "../webfonts1" diff --git a/gen/webfonts1-cli/README.md b/gen/webfonts1-cli/README.md index b6ba14d77f..7ac1c10684 100644 --- a/gen/webfonts1-cli/README.md +++ b/gen/webfonts1-cli/README.md @@ -10,17 +10,19 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *webfonts* API can be found at the +[official documentation site](https://developers.google.com/fonts/docs/developer_api). + # Usage -This documentation was generated from the *webfonts* API at revision *20140210*. The CLI is at version *0.1.0*. +This documentation was generated from the *webfonts* API at revision *20140210*. The CLI is at version *0.2.0*. ```bash - webfonts1 [options] webfonts list [-p <v>...] [-o <out>] +webfonts1 [options] + webfonts + list [-p <v>]... [-o <out>] webfonts1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_webfonts1_cli/index.html - Configuration: --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/webfonts1-cli/mkdocs.yml b/gen/webfonts1-cli/mkdocs.yml index 7ec4e39d12..73f2fd275d 100644 --- a/gen/webfonts1-cli/mkdocs.yml +++ b/gen/webfonts1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: webfonts v0.1.0+20140210 +site_name: webfonts v0.2.0+20140210 site_url: http://byron.github.io/google-apis-rs/google-webfonts1-cli site_description: Write integrating applications with bcore diff --git a/gen/webfonts1-cli/src/cmn.rs b/gen/webfonts1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/webfonts1-cli/src/cmn.rs +++ b/gen/webfonts1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/webfonts1-cli/src/main.rs b/gen/webfonts1-cli/src/main.rs index c3be446659..95fffe2b3c 100644 --- a/gen/webfonts1-cli/src/main.rs +++ b/gen/webfonts1-cli/src/main.rs @@ -2,132 +2,135 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_webfonts1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - webfonts1 [options] webfonts list [-p <v>...] [-o <out>] - webfonts1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_webfonts1_cli/index.html - -Configuration: - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Webfonts<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _webfonts_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { +impl<'n, 'a> Engine<'n, 'a> { + fn _webfonts_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.webfonts().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "sort" => { call = call.sort(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sort"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_webfonts { - if self.opt.cmd_list { - call_result = self._webfonts_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("webfonts", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._webfonts_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("webfonts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } - } else { - unreachable!(); } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -140,7 +143,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -153,7 +156,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -163,37 +166,137 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Webfonts::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("webfonts", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves the list of fonts currently served by the Google Fonts Developer API"##), + "Details at http://byron.github.io/google-apis-rs/google_webfonts1_cli/webfonts_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("webfonts1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20140210") + .about("The Google Fonts Developer API.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_webfonts1_cli") + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/webfonts1/Cargo.toml b/gen/webfonts1/Cargo.toml index 015c3cca46..7cfce0513f 100644 --- a/gen/webfonts1/Cargo.toml +++ b/gen/webfonts1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-webfonts1" -version = "0.1.6+20140210" +version = "0.1.7+20140210" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with webfonts (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/webfonts1" @@ -15,9 +15,10 @@ keywords = ["webfonts", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/webfonts1/README.md b/gen/webfonts1/README.md index 85632c51c8..07ca1d14b6 100644 --- a/gen/webfonts1/README.md +++ b/gen/webfonts1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-webfonts1` library allows access to all features of the *Google webfonts* service. -This documentation was generated from *webfonts* crate version *0.1.6+20140210*, where *20140210* is the exact revision of the *webfonts:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *webfonts* crate version *0.1.7+20140210*, where *20140210* is the exact revision of the *webfonts:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *webfonts* *v1* API can be found at the [official documentation site](https://developers.google.com/fonts/docs/developer_api). @@ -158,7 +158,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_webfonts1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_webfonts1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/webfonts1/src/cmn.rs b/gen/webfonts1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/webfonts1/src/cmn.rs +++ b/gen/webfonts1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/webfonts1/src/lib.rs b/gen/webfonts1/src/lib.rs index 4905cb88f8..6cce34a274 100644 --- a/gen/webfonts1/src/lib.rs +++ b/gen/webfonts1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *webfonts* crate version *0.1.6+20140210*, where *20140210* is the exact revision of the *webfonts:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *webfonts* crate version *0.1.7+20140210*, where *20140210* is the exact revision of the *webfonts:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *webfonts* *v1* API can be found at the //! [official documentation site](https://developers.google.com/fonts/docs/developer_api). @@ -159,7 +159,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -168,7 +168,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -184,6 +183,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -279,7 +279,7 @@ impl<'a, C, A> Webfonts<C, A> Webfonts { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -288,7 +288,7 @@ impl<'a, C, A> Webfonts<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -508,7 +508,7 @@ impl<'a, C, A> WebfontListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -516,7 +516,7 @@ impl<'a, C, A> WebfontListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o loop { let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())); dlg.pre_request(); diff --git a/gen/webmasters3-cli/Cargo.toml b/gen/webmasters3-cli/Cargo.toml index 0851fd2030..6956a65dad 100644 --- a/gen/webmasters3-cli/Cargo.toml +++ b/gen/webmasters3-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-webmasters3-cli" -version = "0.1.0+20140908" +version = "0.2.0+20140908" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with webmasters (protocol v3)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/webmasters3-cli" @@ -17,15 +17,14 @@ keywords = ["webmasters", "google", "cli"] name = "webmasters3" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-webmasters3] path = "../webmasters3" diff --git a/gen/webmasters3-cli/README.md b/gen/webmasters3-cli/README.md index 9dbd49e80e..1e9ac8f0db 100644 --- a/gen/webmasters3-cli/README.md +++ b/gen/webmasters3-cli/README.md @@ -10,32 +10,37 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *webmasters* API can be found at the +[official documentation site](https://developers.google.com/webmaster-tools/v3/welcome). + # Usage -This documentation was generated from the *webmasters* API at revision *20140908*. The CLI is at version *0.1.0*. +This documentation was generated from the *webmasters* API at revision *20140908*. The CLI is at version *0.2.0*. ```bash - webmasters3 [options] sitemaps delete <site-url> <feedpath> [-p <v>...] - webmasters3 [options] sitemaps get <site-url> <feedpath> [-p <v>...] [-o <out>] - webmasters3 [options] sitemaps list <site-url> [-p <v>...] [-o <out>] - webmasters3 [options] sitemaps submit <site-url> <feedpath> [-p <v>...] - webmasters3 [options] sites add <site-url> [-p <v>...] - webmasters3 [options] sites delete <site-url> [-p <v>...] - webmasters3 [options] sites get <site-url> [-p <v>...] [-o <out>] - webmasters3 [options] sites list [-p <v>...] [-o <out>] - webmasters3 [options] urlcrawlerrorscounts query <site-url> [-p <v>...] [-o <out>] - webmasters3 [options] urlcrawlerrorssamples get <site-url> <url> <category> <platform> [-p <v>...] [-o <out>] - webmasters3 [options] urlcrawlerrorssamples list <site-url> <category> <platform> [-p <v>...] [-o <out>] - webmasters3 [options] urlcrawlerrorssamples mark-as-fixed <site-url> <url> <category> <platform> [-p <v>...] +webmasters3 [options] + sitemaps + delete <site-url> <feedpath> [-p <v>]... + get <site-url> <feedpath> [-p <v>]... [-o <out>] + list <site-url> [-p <v>]... [-o <out>] + submit <site-url> <feedpath> [-p <v>]... + sites + add <site-url> [-p <v>]... + delete <site-url> [-p <v>]... + get <site-url> [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + urlcrawlerrorscounts + query <site-url> [-p <v>]... [-o <out>] + urlcrawlerrorssamples + get <site-url> <url> <category> <platform> [-p <v>]... [-o <out>] + list <site-url> <category> <platform> [-p <v>]... [-o <out>] + mark-as-fixed <site-url> <url> <category> <platform> [-p <v>]... webmasters3 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_webmasters3_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/webmasters3-cli/mkdocs.yml b/gen/webmasters3-cli/mkdocs.yml index bc8e5aa82c..ecc775a9cd 100644 --- a/gen/webmasters3-cli/mkdocs.yml +++ b/gen/webmasters3-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: webmasters v0.1.0+20140908 +site_name: webmasters v0.2.0+20140908 site_url: http://byron.github.io/google-apis-rs/google-webmasters3-cli site_description: Write integrating applications with bcore diff --git a/gen/webmasters3-cli/src/cmn.rs b/gen/webmasters3-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/webmasters3-cli/src/cmn.rs +++ b/gen/webmasters3-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/webmasters3-cli/src/main.rs b/gen/webmasters3-cli/src/main.rs index b6297ff616..e99a764ba7 100644 --- a/gen/webmasters3-cli/src/main.rs +++ b/gen/webmasters3-cli/src/main.rs @@ -2,441 +2,428 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_webmasters3 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - webmasters3 [options] sitemaps delete <site-url> <feedpath> [-p <v>...] - webmasters3 [options] sitemaps get <site-url> <feedpath> [-p <v>...] [-o <out>] - webmasters3 [options] sitemaps list <site-url> [-p <v>...] [-o <out>] - webmasters3 [options] sitemaps submit <site-url> <feedpath> [-p <v>...] - webmasters3 [options] sites add <site-url> [-p <v>...] - webmasters3 [options] sites delete <site-url> [-p <v>...] - webmasters3 [options] sites get <site-url> [-p <v>...] [-o <out>] - webmasters3 [options] sites list [-p <v>...] [-o <out>] - webmasters3 [options] urlcrawlerrorscounts query <site-url> [-p <v>...] [-o <out>] - webmasters3 [options] urlcrawlerrorssamples get <site-url> <url> <category> <platform> [-p <v>...] [-o <out>] - webmasters3 [options] urlcrawlerrorssamples list <site-url> <category> <platform> [-p <v>...] [-o <out>] - webmasters3 [options] urlcrawlerrorssamples mark-as-fixed <site-url> <url> <category> <platform> [-p <v>...] - webmasters3 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_webmasters3_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::Webmasters<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _sitemaps_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.sitemaps().delete(&self.opt.arg_site_url, &self.opt.arg_feedpath); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _sitemaps_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.sitemaps().delete(opt.value_of("site-url").unwrap_or(""), opt.value_of("feedpath").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _sitemaps_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.sitemaps().get(&self.opt.arg_site_url, &self.opt.arg_feedpath); - for parg in self.opt.arg_v.iter() { + fn _sitemaps_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.sitemaps().get(opt.value_of("site-url").unwrap_or(""), opt.value_of("feedpath").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _sitemaps_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.sitemaps().list(&self.opt.arg_site_url); - for parg in self.opt.arg_v.iter() { + fn _sitemaps_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.sitemaps().list(opt.value_of("site-url").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "sitemap-index" => { call = call.sitemap_index(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sitemap-index"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _sitemaps_submit(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.sitemaps().submit(&self.opt.arg_site_url, &self.opt.arg_feedpath); - for parg in self.opt.arg_v.iter() { + fn _sitemaps_submit(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.sitemaps().submit(opt.value_of("site-url").unwrap_or(""), opt.value_of("feedpath").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _sites_add(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.sites().add(&self.opt.arg_site_url); - for parg in self.opt.arg_v.iter() { + fn _sites_add(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.sites().add(opt.value_of("site-url").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _sites_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.sites().delete(&self.opt.arg_site_url); - for parg in self.opt.arg_v.iter() { + fn _sites_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.sites().delete(opt.value_of("site-url").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _sites_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.sites().get(&self.opt.arg_site_url); - for parg in self.opt.arg_v.iter() { + fn _sites_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.sites().get(opt.value_of("site-url").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _sites_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _sites_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.sites().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _urlcrawlerrorscounts_query(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.urlcrawlerrorscounts().query(&self.opt.arg_site_url); - for parg in self.opt.arg_v.iter() { + fn _urlcrawlerrorscounts_query(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.urlcrawlerrorscounts().query(opt.value_of("site-url").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "platform" => { @@ -448,246 +435,286 @@ impl Engine { "category" => { call = call.category(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["category", "platform", "latest-counts-only"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _urlcrawlerrorssamples_get(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.urlcrawlerrorssamples().get(&self.opt.arg_site_url, &self.opt.arg_url, &self.opt.arg_category, &self.opt.arg_platform); - for parg in self.opt.arg_v.iter() { + fn _urlcrawlerrorssamples_get(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.urlcrawlerrorssamples().get(opt.value_of("site-url").unwrap_or(""), opt.value_of("url").unwrap_or(""), opt.value_of("category").unwrap_or(""), opt.value_of("platform").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _urlcrawlerrorssamples_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.urlcrawlerrorssamples().list(&self.opt.arg_site_url, &self.opt.arg_category, &self.opt.arg_platform); - for parg in self.opt.arg_v.iter() { + fn _urlcrawlerrorssamples_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.urlcrawlerrorssamples().list(opt.value_of("site-url").unwrap_or(""), opt.value_of("category").unwrap_or(""), opt.value_of("platform").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _urlcrawlerrorssamples_mark_as_fixed(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.urlcrawlerrorssamples().mark_as_fixed(&self.opt.arg_site_url, &self.opt.arg_url, &self.opt.arg_category, &self.opt.arg_platform); - for parg in self.opt.arg_v.iter() { + fn _urlcrawlerrorssamples_mark_as_fixed(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.urlcrawlerrorssamples().mark_as_fixed(opt.value_of("site-url").unwrap_or(""), opt.value_of("url").unwrap_or(""), opt.value_of("category").unwrap_or(""), opt.value_of("platform").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_sitemaps { - if self.opt.cmd_delete { - call_result = self._sitemaps_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._sitemaps_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._sitemaps_list(dry_run, &mut err); - } else if self.opt.cmd_submit { - call_result = self._sitemaps_submit(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("sitemaps", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._sitemaps_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._sitemaps_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._sitemaps_list(opt, dry_run, &mut err); + }, + ("submit", Some(opt)) => { + call_result = self._sitemaps_submit(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("sitemaps".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("sites", Some(opt)) => { + match opt.subcommand() { + ("add", Some(opt)) => { + call_result = self._sites_add(opt, dry_run, &mut err); + }, + ("delete", Some(opt)) => { + call_result = self._sites_delete(opt, dry_run, &mut err); + }, + ("get", Some(opt)) => { + call_result = self._sites_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._sites_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("sites".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("urlcrawlerrorscounts", Some(opt)) => { + match opt.subcommand() { + ("query", Some(opt)) => { + call_result = self._urlcrawlerrorscounts_query(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("urlcrawlerrorscounts".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("urlcrawlerrorssamples", Some(opt)) => { + match opt.subcommand() { + ("get", Some(opt)) => { + call_result = self._urlcrawlerrorssamples_get(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._urlcrawlerrorssamples_list(opt, dry_run, &mut err); + }, + ("mark-as-fixed", Some(opt)) => { + call_result = self._urlcrawlerrorssamples_mark_as_fixed(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("urlcrawlerrorssamples".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_sites { - if self.opt.cmd_add { - call_result = self._sites_add(dry_run, &mut err); - } else if self.opt.cmd_delete { - call_result = self._sites_delete(dry_run, &mut err); - } else if self.opt.cmd_get { - call_result = self._sites_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._sites_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_urlcrawlerrorscounts { - if self.opt.cmd_query { - call_result = self._urlcrawlerrorscounts_query(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_urlcrawlerrorssamples { - if self.opt.cmd_get { - call_result = self._urlcrawlerrorssamples_get(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._urlcrawlerrorssamples_list(dry_run, &mut err); - } else if self.opt.cmd_mark_as_fixed { - call_result = self._urlcrawlerrorssamples_mark_as_fixed(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -700,7 +727,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -713,7 +740,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -723,37 +750,429 @@ impl Engine { let engine = Engine { opt: opt, hub: api::Webmasters::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("sitemaps", "methods: 'delete', 'get', 'list' and 'submit'", vec![ + ("delete", + Some(r##"Deletes a sitemap from this site."##), + "Details at http://byron.github.io/google-apis-rs/google_webmasters3_cli/sitemaps_delete", + vec![ + (Some(r##"site-url"##), + None, + Some(r##"The site's URL, including protocol, for example 'http://www.example.com/'"##), + Some(true), + Some(false)), + + (Some(r##"feedpath"##), + None, + Some(r##"The URL of the actual sitemap (for example http://www.example.com/sitemap.xml)."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves information about a specific sitemap."##), + "Details at http://byron.github.io/google-apis-rs/google_webmasters3_cli/sitemaps_get", + vec![ + (Some(r##"site-url"##), + None, + Some(r##"The site's URL, including protocol, for example 'http://www.example.com/'"##), + Some(true), + Some(false)), + + (Some(r##"feedpath"##), + None, + Some(r##"The URL of the actual sitemap (for example http://www.example.com/sitemap.xml)."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists sitemaps uploaded to the site."##), + "Details at http://byron.github.io/google-apis-rs/google_webmasters3_cli/sitemaps_list", + vec![ + (Some(r##"site-url"##), + None, + Some(r##"The site's URL, including protocol, for example 'http://www.example.com/'"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("submit", + Some(r##"Submits a sitemap for a site."##), + "Details at http://byron.github.io/google-apis-rs/google_webmasters3_cli/sitemaps_submit", + vec![ + (Some(r##"site-url"##), + None, + Some(r##"The site's URL, including protocol, for example 'http://www.example.com/'"##), + Some(true), + Some(false)), + + (Some(r##"feedpath"##), + None, + Some(r##"The URL of the sitemap to add."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ("sites", "methods: 'add', 'delete', 'get' and 'list'", vec![ + ("add", + Some(r##"Adds a site to the set of the user's sites in Webmaster Tools."##), + "Details at http://byron.github.io/google-apis-rs/google_webmasters3_cli/sites_add", + vec![ + (Some(r##"site-url"##), + None, + Some(r##"The URL of the site to add."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("delete", + Some(r##"Removes a site from the set of the user's Webmaster Tools sites."##), + "Details at http://byron.github.io/google-apis-rs/google_webmasters3_cli/sites_delete", + vec![ + (Some(r##"site-url"##), + None, + Some(r##"The site's URL, including protocol, for example 'http://www.example.com/'"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("get", + Some(r##"Retrieves information about specific site."##), + "Details at http://byron.github.io/google-apis-rs/google_webmasters3_cli/sites_get", + vec![ + (Some(r##"site-url"##), + None, + Some(r##"The site's URL, including protocol, for example 'http://www.example.com/'"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists your Webmaster Tools sites."##), + "Details at http://byron.github.io/google-apis-rs/google_webmasters3_cli/sites_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("urlcrawlerrorscounts", "methods: 'query'", vec![ + ("query", + Some(r##"Retrieves a time series of the number of URL crawl errors per error category and platform."##), + "Details at http://byron.github.io/google-apis-rs/google_webmasters3_cli/urlcrawlerrorscounts_query", + vec![ + (Some(r##"site-url"##), + None, + Some(r##"The site's URL, including protocol, for example 'http://www.example.com/'"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("urlcrawlerrorssamples", "methods: 'get', 'list' and 'mark-as-fixed'", vec![ + ("get", + Some(r##"Retrieves details about crawl errors for a site's sample URL."##), + "Details at http://byron.github.io/google-apis-rs/google_webmasters3_cli/urlcrawlerrorssamples_get", + vec![ + (Some(r##"site-url"##), + None, + Some(r##"The site's URL, including protocol, for example 'http://www.example.com/'"##), + Some(true), + Some(false)), + + (Some(r##"url"##), + None, + Some(r##"The relative path (without the site) of the sample URL; must be one of the URLs returned by list"##), + Some(true), + Some(false)), + + (Some(r##"category"##), + None, + Some(r##"The crawl error category, for example 'authPermissions'"##), + Some(true), + Some(false)), + + (Some(r##"platform"##), + None, + Some(r##"The user agent type (platform) that made the request, for example 'web'"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Lists a site's sample URLs for the specified crawl error category and platform."##), + "Details at http://byron.github.io/google-apis-rs/google_webmasters3_cli/urlcrawlerrorssamples_list", + vec![ + (Some(r##"site-url"##), + None, + Some(r##"The site's URL, including protocol, for example 'http://www.example.com/'"##), + Some(true), + Some(false)), + + (Some(r##"category"##), + None, + Some(r##"The crawl error category, for example 'authPermissions'"##), + Some(true), + Some(false)), + + (Some(r##"platform"##), + None, + Some(r##"The user agent type (platform) that made the request, for example 'web'"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("mark-as-fixed", + Some(r##"Marks the provided site's sample URL as fixed, and removes it from the samples list."##), + "Details at http://byron.github.io/google-apis-rs/google_webmasters3_cli/urlcrawlerrorssamples_mark-as-fixed", + vec![ + (Some(r##"site-url"##), + None, + Some(r##"The site's URL, including protocol, for example 'http://www.example.com/'"##), + Some(true), + Some(false)), + + (Some(r##"url"##), + None, + Some(r##"The relative path (without the site) of the sample URL; must be one of the URLs returned by list"##), + Some(true), + Some(false)), + + (Some(r##"category"##), + None, + Some(r##"The crawl error category, for example 'authPermissions'"##), + Some(true), + Some(false)), + + (Some(r##"platform"##), + None, + Some(r##"The user agent type (platform) that made the request, for example 'web'"##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ]), + + ]; + + let mut app = App::new("webmasters3") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20140908") + .about("Lets you view Google Webmaster Tools data for your verified sites.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_webmasters3_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/webmasters3/Cargo.toml b/gen/webmasters3/Cargo.toml index 86838f8148..10fb27f327 100644 --- a/gen/webmasters3/Cargo.toml +++ b/gen/webmasters3/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-webmasters3" -version = "0.1.6+20140908" +version = "0.1.7+20140908" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with webmasters (protocol v3)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/webmasters3" @@ -15,9 +15,10 @@ keywords = ["webmasters", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/webmasters3/README.md b/gen/webmasters3/README.md index 2247c5f8b0..1362dc4d27 100644 --- a/gen/webmasters3/README.md +++ b/gen/webmasters3/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-webmasters3` library allows access to all features of the *Google webmasters* service. -This documentation was generated from *webmasters* crate version *0.1.6+20140908*, where *20140908* is the exact revision of the *webmasters:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *webmasters* crate version *0.1.7+20140908*, where *20140908* is the exact revision of the *webmasters:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *webmasters* *v3* API can be found at the [official documentation site](https://developers.google.com/webmaster-tools/v3/welcome). @@ -163,7 +163,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_webmasters3/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_webmasters3/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/webmasters3/src/cmn.rs b/gen/webmasters3/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/webmasters3/src/cmn.rs +++ b/gen/webmasters3/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/webmasters3/src/lib.rs b/gen/webmasters3/src/lib.rs index 574c0aa9f7..547aff3e64 100644 --- a/gen/webmasters3/src/lib.rs +++ b/gen/webmasters3/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *webmasters* crate version *0.1.6+20140908*, where *20140908* is the exact revision of the *webmasters:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *webmasters* crate version *0.1.7+20140908*, where *20140908* is the exact revision of the *webmasters:v3* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *webmasters* *v3* API can be found at the //! [official documentation site](https://developers.google.com/webmaster-tools/v3/welcome). @@ -164,7 +164,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -173,7 +173,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -189,6 +188,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -309,7 +309,7 @@ impl<'a, C, A> Webmasters<C, A> Webmasters { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -327,7 +327,7 @@ impl<'a, C, A> Webmasters<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1077,7 +1077,7 @@ impl<'a, C, A> SitemapDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1099,7 +1099,7 @@ impl<'a, C, A> SitemapDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1317,7 +1317,7 @@ impl<'a, C, A> SitemapSubmitCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1339,7 +1339,7 @@ impl<'a, C, A> SitemapSubmitCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1558,7 +1558,7 @@ impl<'a, C, A> SitemapGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1580,7 +1580,7 @@ impl<'a, C, A> SitemapGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1812,7 +1812,7 @@ impl<'a, C, A> SitemapListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1834,7 +1834,7 @@ impl<'a, C, A> SitemapListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2058,7 +2058,7 @@ impl<'a, C, A> SiteGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2080,7 +2080,7 @@ impl<'a, C, A> SiteGetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2296,7 +2296,7 @@ impl<'a, C, A> SiteAddCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2318,7 +2318,7 @@ impl<'a, C, A> SiteAddCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oauth access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2499,7 +2499,7 @@ impl<'a, C, A> SiteListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2521,7 +2521,7 @@ impl<'a, C, A> SiteListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oaut access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2727,7 +2727,7 @@ impl<'a, C, A> SiteDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2749,7 +2749,7 @@ impl<'a, C, A> SiteDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2971,7 +2971,7 @@ impl<'a, C, A> UrlcrawlerrorscountQueryCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2993,7 +2993,7 @@ impl<'a, C, A> UrlcrawlerrorscountQueryCall<'a, C, A> where C: BorrowMut<hyper:: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3237,7 +3237,7 @@ impl<'a, C, A> UrlcrawlerrorssampleGetCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3259,7 +3259,7 @@ impl<'a, C, A> UrlcrawlerrorssampleGetCall<'a, C, A> where C: BorrowMut<hyper::C access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3510,7 +3510,7 @@ impl<'a, C, A> UrlcrawlerrorssampleListCall<'a, C, A> where C: BorrowMut<hyper:: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3532,7 +3532,7 @@ impl<'a, C, A> UrlcrawlerrorssampleListCall<'a, C, A> where C: BorrowMut<hyper:: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3774,7 +3774,7 @@ impl<'a, C, A> UrlcrawlerrorssampleMarkAsFixedCall<'a, C, A> where C: BorrowMut< if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3796,7 +3796,7 @@ impl<'a, C, A> UrlcrawlerrorssampleMarkAsFixedCall<'a, C, A> where C: BorrowMut< access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); diff --git a/gen/youtube3-cli/Cargo.toml b/gen/youtube3-cli/Cargo.toml index b9c8403a31..907e949022 100644 --- a/gen/youtube3-cli/Cargo.toml +++ b/gen/youtube3-cli/Cargo.toml @@ -17,13 +17,14 @@ keywords = ["youtube", "google", "cli"] name = "youtube3" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -clap = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-youtube3] path = "../youtube3" diff --git a/gen/youtube3-cli/README.md b/gen/youtube3-cli/README.md index 2cae5ffd60..294558e94d 100644 --- a/gen/youtube3-cli/README.md +++ b/gen/youtube3-cli/README.md @@ -103,9 +103,6 @@ youtube3 [options] unset <channel-id> [-p <v>]... youtube3 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_youtube3_cli - Configuration: [--scope <url>]... Specify the authentication a method should be executed in. Each scope diff --git a/gen/youtube3-cli/src/cmn.rs b/gen/youtube3-cli/src/cmn.rs index f784b283db..3335e7b6bd 100644 --- a/gen/youtube3-cli/src/cmn.rs +++ b/gen/youtube3-cli/src/cmn.rs @@ -4,6 +4,7 @@ use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; use serde::json; use mime::Mime; use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -18,14 +19,54 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + pub enum CallType { Upload(UploadProtocol), Standard, } -pub enum UploadProtocol { - Simple, - Resumable, +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } } impl AsRef<str> for UploadProtocol { @@ -46,18 +87,6 @@ impl AsRef<str> for CallType { } } -impl FromStr for UploadProtocol { - type Err = String; - - fn from_str(s: &str) -> Result<UploadProtocol, String> { - match s { - "simple" => Ok(UploadProtocol::Simple), - "resumable" => Ok(UploadProtocol::Resumable), - _ => Err(format!("Protocol '{}' is unknown", s)), - } - } -} - #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -129,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -153,7 +225,7 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } -pub fn protocol_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { CallType::Upload( match UploadProtocol::from_str(name) { Ok(up) => up, @@ -282,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -304,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -327,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -338,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -347,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -363,7 +448,7 @@ impl fmt::Display for FieldError { pub enum CLIError { Configuration(ConfigurationError), ParseError(&'static str, &'static str, String, String), - UnknownParameter(String), + UnknownParameter(String, Vec<&'static str>), InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), @@ -379,18 +464,24 @@ impl fmt::Display for CLIError { CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) - => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}", proto_name, valid_names.connect(", ")), + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, - CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command"), - CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command", cmd), + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } diff --git a/gen/youtube3-cli/src/main.rs b/gen/youtube3-cli/src/main.rs index 5ad380f534..3029de8d58 100644 --- a/gen/youtube3-cli/src/main.rs +++ b/gen/youtube3-cli/src/main.rs @@ -4,12 +4,14 @@ #![feature(plugin, exit_status)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] +#[macro_use] extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_youtube3 as api; use std::env; @@ -20,7 +22,7 @@ mod cmn; use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, - protocol_from_str}; + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; @@ -37,6 +39,8 @@ enum DoitError { struct Engine<'n, 'a> { opt: ArgMatches<'n, 'a>, hub: api::YouTube<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } @@ -601,7 +605,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["ad-tag", "author", "bulletin", "channel-id", "channel-item", "channel-title", "click-tracking-url", "comment", "content-details", "creative-view-url", "cta-type", "custom-cta-button-text", "default", "description", "description-text", "destination-url", "etag", "favorite", "forecasting-url", "group-id", "height", "high", "id", "image-url", "impression-url", "kind", "like", "maxres", "medium", "playlist-id", "playlist-item", "playlist-item-id", "promoted-item", "published-at", "reason", "recommendation", "reference-url", "resource-id", "seed-resource-id", "snippet", "social", "standard", "subscription", "thumbnails", "title", "type", "upload", "url", "video-id", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -609,22 +614,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -645,7 +649,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -682,22 +688,21 @@ impl<'n, 'a> Engine<'n, 'a> { "channel-id" => { call = call.channel_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "published-before", "channel-id", "mine", "max-results", "region-code", "home", "published-after"] + )); + } + } } } let protocol = CallType::Standard; @@ -718,7 +723,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -737,22 +744,21 @@ impl<'n, 'a> Engine<'n, 'a> { "debug-project-id-override" => { call = call.debug_project_id_override(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of", "debug-project-id-override"] + )); + } + } } } let protocol = CallType::Standard; @@ -794,25 +800,24 @@ impl<'n, 'a> Engine<'n, 'a> { "debug-project-id-override" => { call = call.debug_project_id_override(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - if key == "alt" && value.unwrap_or("unset") == "media" { - download_mode = true; + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + if key == "alt" && value.unwrap_or("unset") == "media" { + download_mode = true; + } + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } } - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["tfmt", "on-behalf-of", "tlang", "debug-project-id-override"] + )); + } + } } } let protocol = CallType::Standard; @@ -934,7 +939,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["audio-track-type", "etag", "failure-reason", "id", "is-auto-synced", "is-cc", "is-draft", "is-easy-reader", "is-large", "kind", "language", "last-updated", "name", "snippet", "status", "track-kind", "video-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -951,26 +957,25 @@ impl<'n, 'a> Engine<'n, 'a> { "debug-project-id-override" => { call = call.debug_project_id_override(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of", "sync", "debug-project-id-override"] + )); + } + } } } let vals = opt.values_of("mode").unwrap(); - let protocol = protocol_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); let mut input_file = input_file_from_opts(vals[1], err); let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { @@ -991,7 +996,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -1013,22 +1020,21 @@ impl<'n, 'a> Engine<'n, 'a> { "debug-project-id-override" => { call = call.debug_project_id_override(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of", "id", "debug-project-id-override"] + )); + } + } } } let protocol = CallType::Standard; @@ -1049,7 +1055,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -1147,7 +1155,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["audio-track-type", "etag", "failure-reason", "id", "is-auto-synced", "is-cc", "is-draft", "is-easy-reader", "is-large", "kind", "language", "last-updated", "name", "snippet", "status", "track-kind", "video-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -1164,26 +1173,25 @@ impl<'n, 'a> Engine<'n, 'a> { "debug-project-id-override" => { call = call.debug_project_id_override(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of", "sync", "debug-project-id-override"] + )); + } + } } } let vals = opt.values_of("mode").unwrap(); - let protocol = protocol_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); let mut input_file = input_file_from_opts(vals[1], err); let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { @@ -1204,7 +1212,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -1241,7 +1251,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.etag = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "kind", "url"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -1252,26 +1263,25 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let vals = opt.values_of("mode").unwrap(); - let protocol = protocol_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); let mut input_file = input_file_from_opts(vals[1], err); let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { @@ -1292,7 +1302,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -1308,22 +1320,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -1466,7 +1477,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["channel-id", "channels", "content-details", "countries", "default-language", "etag", "id", "kind", "languages", "localized", "playlists", "position", "regions", "snippet", "style", "targeting", "title", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -1480,22 +1492,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner-channel", "on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -1516,7 +1527,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -1544,22 +1557,21 @@ impl<'n, 'a> Engine<'n, 'a> { "channel-id" => { call = call.channel_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner", "channel-id", "mine", "hl", "id"] + )); + } + } } } let protocol = CallType::Standard; @@ -1580,7 +1592,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -1707,7 +1721,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["channel-id", "channels", "content-details", "countries", "default-language", "etag", "id", "kind", "languages", "localized", "playlists", "position", "regions", "snippet", "style", "targeting", "title", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -1718,22 +1733,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -1754,7 +1768,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -1797,22 +1813,21 @@ impl<'n, 'a> Engine<'n, 'a> { "category-id" => { call = call.category_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["managed-by-me", "on-behalf-of-content-owner", "for-username", "mine", "max-results", "category-id", "page-token", "my-subscribers", "hl", "id"] + )); + } + } } } let protocol = CallType::Standard; @@ -1833,7 +1848,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -2466,7 +2483,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["audit-details", "background-color", "background-image-url", "banner-external-url", "banner-image-url", "banner-mobile-extra-hd-image-url", "banner-mobile-hd-image-url", "banner-mobile-image-url", "banner-mobile-low-image-url", "banner-mobile-medium-hd-image-url", "banner-tablet-extra-hd-image-url", "banner-tablet-hd-image-url", "banner-tablet-image-url", "banner-tablet-low-image-url", "banner-tv-high-image-url", "banner-tv-image-url", "banner-tv-low-image-url", "banner-tv-medium-image-url", "branding-settings", "channel", "comment-count", "community-guidelines-good-standing", "content-details", "content-id-claims-good-standing", "content-owner", "content-owner-details", "copyright-strikes-good-standing", "corner-position", "country", "default", "default-language", "default-tab", "default-timing", "description", "duration-ms", "etag", "favorites", "featured-channels-title", "featured-channels-urls", "featured-playlist-id", "google-plus-user-id", "height", "hidden-subscriber-count", "high", "id", "image", "invideo-promotion", "is-linked", "keywords", "kind", "large-branded-banner-image-imap-script", "large-branded-banner-image-url", "likes", "localized", "long-uploads-status", "maxres", "medium", "moderate-comments", "offset-ms", "overall-good-standing", "position", "privacy-status", "profile-color", "published-at", "related-playlists", "show-browse-view", "show-related-channels", "small-branded-banner-image-imap-script", "small-branded-banner-image-url", "snippet", "standard", "statistics", "status", "subscriber-count", "text-color", "thumbnails", "time-linked", "title", "topic-details", "topic-ids", "tracking-analytics-account-id", "tracking-image-url", "type", "unsubscribed-trailer", "uploads", "url", "use-smart-timing", "value", "video-count", "view-count", "watch", "watch-history", "watch-icon-image-url", "watch-later", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -2477,22 +2495,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -2513,7 +2530,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -2676,7 +2695,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author-channel-id", "author-channel-url", "author-display-name", "author-googleplus-profile-url", "author-profile-image-url", "can-rate", "can-reply", "channel-id", "etag", "id", "is-public", "kind", "like-count", "moderation-status", "parent-id", "published-at", "snippet", "text-display", "text-original", "top-level-comment", "total-reply-count", "updated-at", "value", "video-id", "viewer-rating"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -2687,22 +2707,21 @@ impl<'n, 'a> Engine<'n, 'a> { "share-on-google-plus" => { call = call.share_on_google_plus(arg_from_str(value.unwrap_or("false"), err, "share-on-google-plus", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["share-on-google-plus"] + )); + } + } } } let protocol = CallType::Standard; @@ -2723,7 +2742,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -2763,22 +2784,21 @@ impl<'n, 'a> Engine<'n, 'a> { "all-threads-related-to-channel-id" => { call = call.all_threads_related_to_channel_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["all-threads-related-to-channel-id", "channel-id", "video-id", "max-results", "page-token", "search-terms", "text-format", "id", "moderation-status"] + )); + } + } } } let protocol = CallType::Standard; @@ -2799,7 +2819,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -2962,7 +2984,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author-channel-id", "author-channel-url", "author-display-name", "author-googleplus-profile-url", "author-profile-image-url", "can-rate", "can-reply", "channel-id", "etag", "id", "is-public", "kind", "like-count", "moderation-status", "parent-id", "published-at", "snippet", "text-display", "text-original", "top-level-comment", "total-reply-count", "updated-at", "value", "video-id", "viewer-rating"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -2970,22 +2993,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -3006,7 +3028,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -3019,22 +3043,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -3167,7 +3190,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author-channel-id", "author-channel-url", "author-display-name", "author-googleplus-profile-url", "author-profile-image-url", "can-rate", "channel-id", "etag", "id", "kind", "like-count", "moderation-status", "parent-id", "published-at", "snippet", "text-display", "text-original", "updated-at", "value", "video-id", "viewer-rating"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -3175,22 +3199,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -3211,7 +3234,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -3239,22 +3264,21 @@ impl<'n, 'a> Engine<'n, 'a> { "id" => { call = call.id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["page-token", "text-format", "id", "max-results", "parent-id"] + )); + } + } } } let protocol = CallType::Standard; @@ -3275,7 +3299,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -3288,22 +3314,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -3335,22 +3360,21 @@ impl<'n, 'a> Engine<'n, 'a> { "ban-author" => { call = call.ban_author(arg_from_str(value.unwrap_or("false"), err, "ban-author", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["ban-author"] + )); + } + } } } let protocol = CallType::Standard; @@ -3483,7 +3507,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["author-channel-id", "author-channel-url", "author-display-name", "author-googleplus-profile-url", "author-profile-image-url", "can-rate", "channel-id", "etag", "id", "kind", "like-count", "moderation-status", "parent-id", "published-at", "snippet", "text-display", "text-original", "updated-at", "value", "video-id", "viewer-rating"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -3491,22 +3516,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -3527,7 +3551,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -3549,22 +3575,21 @@ impl<'n, 'a> Engine<'n, 'a> { "hl" => { call = call.hl(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["region-code", "id", "hl"] + )); + } + } } } let protocol = CallType::Standard; @@ -3585,7 +3610,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -3601,22 +3628,21 @@ impl<'n, 'a> Engine<'n, 'a> { "hl" => { call = call.hl(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["hl"] + )); + } + } } } let protocol = CallType::Standard; @@ -3637,7 +3663,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -3653,22 +3681,21 @@ impl<'n, 'a> Engine<'n, 'a> { "hl" => { call = call.hl(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["hl"] + )); + } + } } } let protocol = CallType::Standard; @@ -3689,7 +3716,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -3711,22 +3740,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner-channel", "on-behalf-of-content-owner", "stream-id"] + )); + } + } } } let protocol = CallType::Standard; @@ -3747,7 +3775,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -3775,22 +3805,21 @@ impl<'n, 'a> Engine<'n, 'a> { "display-slate" => { call = call.display_slate(arg_from_str(value.unwrap_or("false"), err, "display-slate", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner-channel", "on-behalf-of-content-owner", "display-slate", "offset-time-ms", "walltime"] + )); + } + } } } let protocol = CallType::Standard; @@ -3811,7 +3840,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -3830,22 +3861,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner-channel", "on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -4120,7 +4150,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["actual-end-time", "actual-start-time", "bound-stream-id", "broadcast-stream-delay-ms", "channel-id", "content-details", "default", "description", "embed-html", "enable-closed-captions", "enable-content-encryption", "enable-dvr", "enable-embed", "enable-monitor-stream", "etag", "height", "high", "id", "is-default-broadcast", "kind", "life-cycle-status", "live-broadcast-priority", "maxres", "medium", "monitor-stream", "privacy-status", "published-at", "record-from-start", "recording-status", "scheduled-end-time", "scheduled-start-time", "snippet", "standard", "start-with-slate", "status", "thumbnails", "title", "url", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -4134,22 +4165,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner-channel", "on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -4170,7 +4200,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4204,22 +4236,21 @@ impl<'n, 'a> Engine<'n, 'a> { "broadcast-status" => { call = call.broadcast_status(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["broadcast-status", "on-behalf-of-content-owner", "on-behalf-of-content-owner-channel", "mine", "max-results", "page-token", "id"] + )); + } + } } } let protocol = CallType::Standard; @@ -4240,7 +4271,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4259,22 +4292,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner-channel", "on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -4295,7 +4327,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4554,7 +4588,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["actual-end-time", "actual-start-time", "bound-stream-id", "broadcast-stream-delay-ms", "channel-id", "content-details", "default", "description", "embed-html", "enable-closed-captions", "enable-content-encryption", "enable-dvr", "enable-embed", "enable-monitor-stream", "etag", "height", "high", "id", "is-default-broadcast", "kind", "life-cycle-status", "live-broadcast-priority", "maxres", "medium", "monitor-stream", "privacy-status", "published-at", "record-from-start", "recording-status", "scheduled-end-time", "scheduled-start-time", "snippet", "standard", "start-with-slate", "status", "thumbnails", "title", "url", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -4568,22 +4603,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner-channel", "on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -4604,7 +4638,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4623,22 +4659,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner-channel", "on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -4777,7 +4812,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["backup-ingestion-address", "cdn", "channel-id", "closed-captions-ingestion-url", "content-details", "description", "etag", "format", "id", "ingestion-address", "ingestion-info", "ingestion-type", "is-default-stream", "is-reusable", "kind", "published-at", "snippet", "status", "stream-name", "stream-status", "title"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -4791,22 +4827,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner-channel", "on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -4827,7 +4862,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -4858,22 +4895,21 @@ impl<'n, 'a> Engine<'n, 'a> { "id" => { call = call.id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner", "on-behalf-of-content-owner-channel", "mine", "max-results", "page-token", "id"] + )); + } + } } } let protocol = CallType::Standard; @@ -4894,7 +4930,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -5017,7 +5055,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["backup-ingestion-address", "cdn", "channel-id", "closed-captions-ingestion-url", "content-details", "description", "etag", "format", "id", "ingestion-address", "ingestion-info", "ingestion-type", "is-default-stream", "is-reusable", "kind", "published-at", "snippet", "status", "stream-name", "stream-status", "title"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -5031,22 +5070,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner-channel", "on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -5067,7 +5105,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -5080,22 +5120,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -5342,7 +5381,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["channel-id", "channel-title", "content-details", "default", "description", "end-at", "etag", "height", "high", "id", "kind", "maxres", "medium", "note", "playlist-id", "position", "privacy-status", "published-at", "resource-id", "snippet", "standard", "start-at", "status", "thumbnails", "title", "url", "video-id", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -5353,22 +5393,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -5389,7 +5428,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -5420,22 +5461,21 @@ impl<'n, 'a> Engine<'n, 'a> { "id" => { call = call.id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner", "playlist-id", "video-id", "max-results", "page-token", "id"] + )); + } + } } } let protocol = CallType::Standard; @@ -5456,7 +5496,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -5687,7 +5729,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["channel-id", "channel-title", "content-details", "default", "description", "end-at", "etag", "height", "high", "id", "kind", "maxres", "medium", "note", "playlist-id", "position", "privacy-status", "published-at", "resource-id", "snippet", "standard", "start-at", "status", "thumbnails", "title", "url", "video-id", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -5695,22 +5738,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -5731,7 +5773,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -5747,22 +5791,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -6002,7 +6045,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["channel-id", "channel-title", "content-details", "default", "default-language", "description", "embed-html", "etag", "height", "high", "id", "item-count", "kind", "localized", "maxres", "medium", "player", "privacy-status", "published-at", "snippet", "standard", "status", "tags", "thumbnails", "title", "url", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -6016,22 +6060,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner-channel", "on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -6052,7 +6095,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -6089,22 +6134,21 @@ impl<'n, 'a> Engine<'n, 'a> { "channel-id" => { call = call.channel_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner", "on-behalf-of-content-owner-channel", "channel-id", "mine", "max-results", "page-token", "hl", "id"] + )); + } + } } } let protocol = CallType::Standard; @@ -6125,7 +6169,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -6349,7 +6395,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["channel-id", "channel-title", "content-details", "default", "default-language", "description", "embed-html", "etag", "height", "high", "id", "item-count", "kind", "localized", "maxres", "medium", "player", "privacy-status", "published-at", "snippet", "standard", "status", "tags", "thumbnails", "title", "url", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -6360,22 +6407,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -6396,7 +6442,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -6499,22 +6547,21 @@ impl<'n, 'a> Engine<'n, 'a> { "channel-id" => { call = call.channel_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["location-radius", "channel-id", "video-syndicated", "event-type", "channel-type", "video-caption", "published-after", "on-behalf-of-content-owner", "video-category-id", "for-content-owner", "region-code", "location", "for-developer", "video-type", "type", "topic-id", "published-before", "video-dimension", "video-license", "max-results", "related-to-video-id", "video-definition", "page-token", "video-duration", "relevance-language", "for-mine", "q", "safe-search", "video-embeddable", "order"] + )); + } + } } } let protocol = CallType::Standard; @@ -6535,7 +6582,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -6548,22 +6597,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -6907,7 +6955,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["activity-type", "channel-id", "channel-title", "content-details", "default", "description", "etag", "height", "high", "id", "kind", "maxres", "medium", "new-item-count", "playlist-id", "published-at", "resource-id", "snippet", "standard", "subscriber-snippet", "thumbnails", "title", "total-item-count", "url", "video-id", "width"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -6915,22 +6964,21 @@ impl<'n, 'a> Engine<'n, 'a> { for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } let protocol = CallType::Standard; @@ -6951,7 +6999,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -6994,22 +7044,21 @@ impl<'n, 'a> Engine<'n, 'a> { "channel-id" => { call = call.channel_id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner", "on-behalf-of-content-owner-channel", "channel-id", "mine", "max-results", "id", "page-token", "my-subscribers", "for-channel-id", "order"] + )); + } + } } } let protocol = CallType::Standard; @@ -7030,7 +7079,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -7046,26 +7097,25 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let vals = opt.values_of("mode").unwrap(); - let protocol = protocol_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); let mut input_file = input_file_from_opts(vals[1], err); let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { @@ -7086,7 +7136,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -7102,22 +7154,21 @@ impl<'n, 'a> Engine<'n, 'a> { "hl" => { call = call.hl(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["hl"] + )); + } + } } } let protocol = CallType::Standard; @@ -7138,7 +7189,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -7160,22 +7213,21 @@ impl<'n, 'a> Engine<'n, 'a> { "hl" => { call = call.hl(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["region-code", "id", "hl"] + )); + } + } } } let protocol = CallType::Standard; @@ -7196,7 +7248,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -7212,22 +7266,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -7259,22 +7312,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -7295,7 +7347,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -8176,7 +8230,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["acb-rating", "access", "actual-end-time", "actual-start-time", "agcom-rating", "age-gating", "alcohol-content", "allowed", "altitude", "anatel-rating", "bbfc-rating", "bfvc-rating", "bitrate-bps", "blocked", "bmukk-rating", "caption", "category-id", "catv-rating", "catvfr-rating", "cbfc-rating", "ccc-rating", "cce-rating", "channel-id", "channel-title", "chfilm-rating", "chvrs-rating", "cicf-rating", "cna-rating", "comment-count", "concurrent-viewers", "container", "content-details", "content-rating", "country-restriction", "creation-time", "csa-rating", "cscf-rating", "czfilm-rating", "default", "default-language", "definition", "description", "dimension", "dislike-count", "djctq-rating", "djctq-rating-reasons", "duration", "duration-ms", "editor-suggestions", "editor-suggestions-availability", "eefilm-rating", "egfilm-rating", "eirin-rating", "embed-html", "embeddable", "etag", "exception", "failure-reason", "favorite-count", "fcbm-rating", "fco-rating", "file-details", "file-details-availability", "file-name", "file-size", "file-type", "fmoc-rating", "fpb-rating", "fsk-rating", "grfilm-rating", "height", "high", "icaa-rating", "id", "ifco-rating", "ilfilm-rating", "incaa-rating", "kfcb-rating", "kijkwijzer-rating", "kind", "kmrb-rating", "latitude", "license", "licensed-content", "like-count", "live-broadcast-content", "live-streaming-details", "localized", "location", "location-description", "longitude", "lsf-rating", "maxres", "mccaa-rating", "mccyp-rating", "mda-rating", "medietilsynet-rating", "medium", "meku-rating", "mibac-rating", "moc-rating", "moctw-rating", "monetization-details", "mpaa-rating", "mtrcb-rating", "nbc-rating", "nbcpl-rating", "nfrc-rating", "nfvcb-rating", "nkclv-rating", "oflc-rating", "parts-processed", "parts-total", "pefilm-rating", "player", "privacy-status", "processing-details", "processing-errors", "processing-failure-reason", "processing-hints", "processing-issues-availability", "processing-progress", "processing-status", "processing-warnings", "project-details", "public-stats-viewable", "publish-at", "published-at", "rcnof-rating", "recording-date", "recording-details", "recording-location", "region-restriction", "rejection-reason", "relevant-topic-ids", "resorteviolencia-rating", "restricted", "rtc-rating", "rte-rating", "russia-rating", "scheduled-end-time", "scheduled-start-time", "skfilm-rating", "smais-rating", "smsa-rating", "snippet", "standard", "statistics", "status", "suggestions", "tag-suggestions-availability", "tags", "thumbnails", "thumbnails-availability", "time-left-ms", "title", "topic-details", "topic-ids", "tvpg-rating", "upload-status", "url", "video-game-rating", "view-count", "width", "yt-rating"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -8199,26 +8254,25 @@ impl<'n, 'a> Engine<'n, 'a> { "auto-levels" => { call = call.auto_levels(arg_from_str(value.unwrap_or("false"), err, "auto-levels", "boolean")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner-channel", "on-behalf-of-content-owner", "auto-levels", "notify-subscribers", "stabilize"] + )); + } + } } } let vals = opt.values_of("mode").unwrap(); - let protocol = protocol_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); let mut input_file = input_file_from_opts(vals[1], err); let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { @@ -8239,7 +8293,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -8282,22 +8338,21 @@ impl<'n, 'a> Engine<'n, 'a> { "chart" => { call = call.chart(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner", "region-code", "page-token", "locale", "chart", "max-results", "video-category-id", "hl", "my-rating", "id"] + )); + } + } } } let protocol = CallType::Standard; @@ -8318,7 +8373,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -8334,22 +8391,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -8408,7 +8464,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.video_id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["comments", "language", "reason-id", "secondary-reason-id", "video-id"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -8419,22 +8476,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -9331,7 +9387,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["acb-rating", "access", "actual-end-time", "actual-start-time", "agcom-rating", "age-gating", "alcohol-content", "allowed", "altitude", "anatel-rating", "bbfc-rating", "bfvc-rating", "bitrate-bps", "blocked", "bmukk-rating", "caption", "category-id", "catv-rating", "catvfr-rating", "cbfc-rating", "ccc-rating", "cce-rating", "channel-id", "channel-title", "chfilm-rating", "chvrs-rating", "cicf-rating", "cna-rating", "comment-count", "concurrent-viewers", "container", "content-details", "content-rating", "country-restriction", "creation-time", "csa-rating", "cscf-rating", "czfilm-rating", "default", "default-language", "definition", "description", "dimension", "dislike-count", "djctq-rating", "djctq-rating-reasons", "duration", "duration-ms", "editor-suggestions", "editor-suggestions-availability", "eefilm-rating", "egfilm-rating", "eirin-rating", "embed-html", "embeddable", "etag", "exception", "failure-reason", "favorite-count", "fcbm-rating", "fco-rating", "file-details", "file-details-availability", "file-name", "file-size", "file-type", "fmoc-rating", "fpb-rating", "fsk-rating", "grfilm-rating", "height", "high", "icaa-rating", "id", "ifco-rating", "ilfilm-rating", "incaa-rating", "kfcb-rating", "kijkwijzer-rating", "kind", "kmrb-rating", "latitude", "license", "licensed-content", "like-count", "live-broadcast-content", "live-streaming-details", "localized", "location", "location-description", "longitude", "lsf-rating", "maxres", "mccaa-rating", "mccyp-rating", "mda-rating", "medietilsynet-rating", "medium", "meku-rating", "mibac-rating", "moc-rating", "moctw-rating", "monetization-details", "mpaa-rating", "mtrcb-rating", "nbc-rating", "nbcpl-rating", "nfrc-rating", "nfvcb-rating", "nkclv-rating", "oflc-rating", "parts-processed", "parts-total", "pefilm-rating", "player", "privacy-status", "processing-details", "processing-errors", "processing-failure-reason", "processing-hints", "processing-issues-availability", "processing-progress", "processing-status", "processing-warnings", "project-details", "public-stats-viewable", "publish-at", "published-at", "rcnof-rating", "recording-date", "recording-details", "recording-location", "region-restriction", "rejection-reason", "relevant-topic-ids", "resorteviolencia-rating", "restricted", "rtc-rating", "rte-rating", "russia-rating", "scheduled-end-time", "scheduled-start-time", "skfilm-rating", "smais-rating", "smsa-rating", "snippet", "standard", "statistics", "status", "suggestions", "tag-suggestions-availability", "tags", "thumbnails", "thumbnails-availability", "time-left-ms", "title", "topic-details", "topic-ids", "tvpg-rating", "upload-status", "url", "video-game-rating", "view-count", "width", "yt-rating"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -9342,22 +9399,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -9378,7 +9434,9 @@ impl<'n, 'a> Engine<'n, 'a> { } { Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); Ok(()) } } @@ -9449,7 +9507,8 @@ impl<'n, 'a> Engine<'n, 'a> { request.image_bytes = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["corner-position", "duration-ms", "image-bytes", "image-url", "offset-ms", "position", "target-channel-id", "timing", "type"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } @@ -9460,26 +9519,25 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let vals = opt.values_of("mode").unwrap(); - let protocol = protocol_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); + let protocol = calltype_from_str(vals[0], ["simple", "resumable"].iter().map(|&v| v.to_string()).collect(), err); let mut input_file = input_file_from_opts(vals[1], err); let mime_type = input_mime_from_opts(opt.value_of("mime").unwrap_or("application/octet-stream"), err); if dry_run { @@ -9511,22 +9569,21 @@ impl<'n, 'a> Engine<'n, 'a> { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } let protocol = CallType::Standard; @@ -9974,6 +10031,13 @@ impl<'n, 'a> Engine<'n, 'a> { let engine = Engine { opt: opt, hub: api::YouTube::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { @@ -9995,1303 +10059,1425 @@ fn main() { let upload_value_names = ["mode", "file"]; let arg_data = [ ("activities", "methods: 'insert' and 'list'", vec![ - ("insert", Some("Posts a bulletin for a specific channel. (The user submitting the request must be authorized to act on the channel's behalf.) + ("insert", + Some(r##"Posts a bulletin for a specific channel. (The user submitting the request must be authorized to act on the channel's behalf.) - Note: Even though an activity resource can contain information about actions like a user rating a video or marking a video as a favorite, you need to use other API methods to generate those activity resources. For example, you would use the API's videos.rate() method to rate a video and the playlistItems.insert() method to mark a video as a favorite."), + Note: Even though an activity resource can contain information about actions like a user rating a video or marking a video as a favorite, you need to use other API methods to generate those activity resources. For example, you would use the API's videos.rate() method to rate a video and the playlistItems.insert() method to mark a video as a favorite."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/activities_insert", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Returns a list of channel activity events that match the request criteria. For example, you can retrieve events associated with a particular channel, events associated with the user's subscriptions and Google+ friends, or the YouTube home page feed, which is customized for each user."), + ("list", + Some(r##"Returns a list of channel activity events that match the request criteria. For example, you can retrieve events associated with a particular channel, events associated with the user's subscriptions and Google+ friends, or the YouTube home page feed, which is customized for each user."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/activities_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more activity resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, and contentDetails. + Some(r##"The part parameter specifies a comma-separated list of one or more activity resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, and contentDetails. - If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a activity resource, the snippet property contains other properties that identify the type of activity, a display title for the activity, and so forth. If you set part=snippet, the API response will also contain all of those nested properties."), + If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a activity resource, the snippet property contains other properties that identify the type of activity, a display title for the activity, and so forth. If you set part=snippet, the API response will also contain all of those nested properties."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("captions", "methods: 'delete', 'download', 'insert', 'list' and 'update'", vec![ - ("delete", Some("Deletes a specified caption track."), + ("delete", + Some(r##"Deletes a specified caption track."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/captions_delete", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter identifies the caption track that is being deleted. The value is a caption track ID as identified by the id property in a caption resource."), + Some(r##"The id parameter identifies the caption track that is being deleted. The value is a caption track ID as identified by the id property in a caption resource."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("download", Some("Downloads a caption track. The caption track is returned in its original format unless the request specifies a value for the tfmt parameter and in its original language unless the request specifies a value for the tlang parameter."), + ("download", + Some(r##"Downloads a caption track. The caption track is returned in its original format unless the request specifies a value for the tfmt parameter and in its original language unless the request specifies a value for the tlang parameter."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/captions_download", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter identifies the caption track that is being retrieved. The value is a caption track ID as identified by the id property in a caption resource."), + Some(r##"The id parameter identifies the caption track that is being retrieved. The value is a caption track ID as identified by the id property in a caption resource."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("insert", Some("Uploads a caption track."), + ("insert", + Some(r##"Uploads a caption track."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/captions_insert", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("mode"), - Some("u"), - Some("Specify the upload protocol (simple|resumable) and the file to upload"), + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Returns a list of caption tracks that are associated with a specified video. Note that the API response does not contain the actual captions and that the captions.download method provides the ability to retrieve a caption track."), + ("list", + Some(r##"Returns a list of caption tracks that are associated with a specified video. Note that the API response does not contain the actual captions and that the captions.download method provides the ability to retrieve a caption track."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/captions_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more caption resource parts that the API response will include. The part names that you can include in the parameter value are id and snippet."), + Some(r##"The part parameter specifies a comma-separated list of one or more caption resource parts that the API response will include. The part names that you can include in the parameter value are id and snippet."##), Some(true), Some(false)), - (Some("video-id"), + (Some(r##"video-id"##), None, - Some("The videoId parameter specifies the YouTube video ID of the video for which the API should return caption tracks."), + Some(r##"The videoId parameter specifies the YouTube video ID of the video for which the API should return caption tracks."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Updates a caption track. When updating a caption track, you can change the track's draft status, upload a new caption file for the track, or both."), + ("update", + Some(r##"Updates a caption track. When updating a caption track, you can change the track's draft status, upload a new caption file for the track, or both."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/captions_update", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("mode"), - Some("u"), - Some("Specify the upload protocol (simple|resumable) and the file to upload"), + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("channel-banners", "methods: 'insert'", vec![ - ("insert", Some("Uploads a channel banner image to YouTube. This method represents the first two steps in a three-step process to update the banner image for a channel: + ("insert", + Some(r##"Uploads a channel banner image to YouTube. This method represents the first two steps in a three-step process to update the banner image for a channel: - Call the channelBanners.insert method to upload the binary image data to YouTube. The image must have a 16:9 aspect ratio and be at least 2120x1192 pixels. - Extract the url property's value from the response that the API returns for step 1. - - Call the channels.update method to update the channel's branding settings. Set the brandingSettings.image.bannerExternalUrl property's value to the URL obtained in step 2."), + - Call the channels.update method to update the channel's branding settings. Set the brandingSettings.image.bannerExternalUrl property's value to the URL obtained in step 2."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/channel-banners_insert", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("mode"), - Some("u"), - Some("Specify the upload protocol (simple|resumable) and the file to upload"), + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("channel-sections", "methods: 'delete', 'insert', 'list' and 'update'", vec![ - ("delete", Some("Deletes a channelSection."), + ("delete", + Some(r##"Deletes a channelSection."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/channel-sections_delete", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies the YouTube channelSection ID for the resource that is being deleted. In a channelSection resource, the id property specifies the YouTube channelSection ID."), + Some(r##"The id parameter specifies the YouTube channelSection ID for the resource that is being deleted. In a channelSection resource, the id property specifies the YouTube channelSection ID."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("insert", Some("Adds a channelSection for the authenticated user's channel."), + ("insert", + Some(r##"Adds a channelSection for the authenticated user's channel."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/channel-sections_insert", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Returns channelSection resources that match the API request criteria."), + ("list", + Some(r##"Returns channelSection resources that match the API request criteria."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/channel-sections_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more channelSection resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, and contentDetails. + Some(r##"The part parameter specifies a comma-separated list of one or more channelSection resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, and contentDetails. - If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a channelSection resource, the snippet property contains other properties, such as a display title for the channelSection. If you set part=snippet, the API response will also contain all of those nested properties."), + If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a channelSection resource, the snippet property contains other properties, such as a display title for the channelSection. If you set part=snippet, the API response will also contain all of those nested properties."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Update a channelSection."), + ("update", + Some(r##"Update a channelSection."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/channel-sections_update", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("channels", "methods: 'list' and 'update'", vec![ - ("list", Some("Returns a collection of zero or more channel resources that match the request criteria."), + ("list", + Some(r##"Returns a collection of zero or more channel resources that match the request criteria."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/channels_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more channel resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, contentDetails, statistics, topicDetails, and invideoPromotion. + Some(r##"The part parameter specifies a comma-separated list of one or more channel resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, contentDetails, statistics, topicDetails, and invideoPromotion. - If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a channel resource, the contentDetails property contains other properties, such as the uploads properties. As such, if you set part=contentDetails, the API response will also contain all of those nested properties."), + If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a channel resource, the contentDetails property contains other properties, such as the uploads properties. As such, if you set part=contentDetails, the API response will also contain all of those nested properties."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Updates a channel's metadata."), + ("update", + Some(r##"Updates a channel's metadata."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/channels_update", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("comment-threads", "methods: 'insert', 'list' and 'update'", vec![ - ("insert", Some("Creates a new comment thread and top level comment."), + ("insert", + Some(r##"Creates a new comment thread and top level comment."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/comment-threads_insert", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Returns a list of comment threads that match the API request parameters."), + ("list", + Some(r##"Returns a list of comment threads that match the API request parameters."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/comment-threads_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies the commentThread resource parts that the API response will include. Supported values are id, snippet and replies."), + Some(r##"The part parameter specifies the commentThread resource parts that the API response will include. Supported values are id, snippet and replies."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Modifies an existing comment."), + ("update", + Some(r##"Modifies an existing comment."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/comment-threads_update", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("comments", "methods: 'delete', 'insert', 'list', 'mark-as-spam', 'set-moderation-status' and 'update'", vec![ - ("delete", Some("Deletes a comment."), + ("delete", + Some(r##"Deletes a comment."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/comments_delete", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies the comment ID for the resource that should be deleted."), + Some(r##"The id parameter specifies the comment ID for the resource that should be deleted."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("insert", Some("Creates a new comment. + ("insert", + Some(r##"Creates a new comment. - Note: to create a top level comment it is also necessary to create a comment thread. Both are accomplished through the commentThreads resource."), + Note: to create a top level comment it is also necessary to create a comment thread. Both are accomplished through the commentThreads resource."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/comments_insert", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Returns a list of comments that match the API request parameters."), + ("list", + Some(r##"Returns a list of comments that match the API request parameters."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/comments_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies the comment resource parts that the API response will include. Supported values are id and snippet."), + Some(r##"The part parameter specifies the comment resource parts that the API response will include. Supported values are id and snippet."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("mark-as-spam", Some("Expresses the caller's opinion that a comment is spam."), + ("mark-as-spam", + Some(r##"Expresses the caller's opinion that a comment is spam."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/comments_mark-as-spam", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies a comma-separated list of IDs of comments which should get flagged as spam."), + Some(r##"The id parameter specifies a comma-separated list of IDs of comments which should get flagged as spam."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("set-moderation-status", Some("Sets the moderation status of one or more comments."), + ("set-moderation-status", + Some(r##"Sets the moderation status of one or more comments."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/comments_set-moderation-status", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies a comma-separated list of IDs of comments whose moderation status should be updated."), + Some(r##"The id parameter specifies a comma-separated list of IDs of comments whose moderation status should be updated."##), Some(true), Some(false)), - (Some("moderation-status"), + (Some(r##"moderation-status"##), None, - Some("Determines the new moderation status of the specified comments."), + Some(r##"Determines the new moderation status of the specified comments."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("update", Some("Modifies an existing comment."), + ("update", + Some(r##"Modifies an existing comment."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/comments_update", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("guide-categories", "methods: 'list'", vec![ - ("list", Some("Returns a list of categories that can be associated with YouTube channels."), + ("list", + Some(r##"Returns a list of categories that can be associated with YouTube channels."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/guide-categories_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more guideCategory resource properties that the API response will include. The part names that you can include in the parameter value are id and snippet. + Some(r##"The part parameter specifies a comma-separated list of one or more guideCategory resource properties that the API response will include. The part names that you can include in the parameter value are id and snippet. - If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a guideCategory resource, the snippet property contains other properties, such as the category's title. If you set part=snippet, the API response will also contain all of those nested properties."), + If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a guideCategory resource, the snippet property contains other properties, such as the category's title. If you set part=snippet, the API response will also contain all of those nested properties."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("i18n-languages", "methods: 'list'", vec![ - ("list", Some("Returns a list of supported languages."), + ("list", + Some(r##"Returns a list of supported languages."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/i18n-languages_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more i18nLanguage resource properties that the API response will include. The part names that you can include in the parameter value are id and snippet."), + Some(r##"The part parameter specifies a comma-separated list of one or more i18nLanguage resource properties that the API response will include. The part names that you can include in the parameter value are id and snippet."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("i18n-regions", "methods: 'list'", vec![ - ("list", Some("Returns a list of supported regions."), + ("list", + Some(r##"Returns a list of supported regions."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/i18n-regions_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more i18nRegion resource properties that the API response will include. The part names that you can include in the parameter value are id and snippet."), + Some(r##"The part parameter specifies a comma-separated list of one or more i18nRegion resource properties that the API response will include. The part names that you can include in the parameter value are id and snippet."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("live-broadcasts", "methods: 'bind', 'control', 'delete', 'insert', 'list', 'transition' and 'update'", vec![ - ("bind", Some("Binds a YouTube broadcast to a stream or removes an existing binding between a broadcast and a stream. A broadcast can only be bound to one video stream."), + ("bind", + Some(r##"Binds a YouTube broadcast to a stream or removes an existing binding between a broadcast and a stream. A broadcast can only be bound to one video stream."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/live-broadcasts_bind", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies the unique ID of the broadcast that is being bound to a video stream."), + Some(r##"The id parameter specifies the unique ID of the broadcast that is being bound to a video stream."##), Some(true), Some(false)), - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more liveBroadcast resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, contentDetails, and status."), + Some(r##"The part parameter specifies a comma-separated list of one or more liveBroadcast resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, contentDetails, and status."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("control", Some("Controls the settings for a slate that can be displayed in the broadcast stream."), + ("control", + Some(r##"Controls the settings for a slate that can be displayed in the broadcast stream."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/live-broadcasts_control", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies the YouTube live broadcast ID that uniquely identifies the broadcast in which the slate is being updated."), + Some(r##"The id parameter specifies the YouTube live broadcast ID that uniquely identifies the broadcast in which the slate is being updated."##), Some(true), Some(false)), - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more liveBroadcast resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, contentDetails, and status."), + Some(r##"The part parameter specifies a comma-separated list of one or more liveBroadcast resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, contentDetails, and status."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("delete", Some("Deletes a broadcast."), + ("delete", + Some(r##"Deletes a broadcast."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/live-broadcasts_delete", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies the YouTube live broadcast ID for the resource that is being deleted."), + Some(r##"The id parameter specifies the YouTube live broadcast ID for the resource that is being deleted."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("insert", Some("Creates a broadcast."), + ("insert", + Some(r##"Creates a broadcast."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/live-broadcasts_insert", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Returns a list of YouTube broadcasts that match the API request parameters."), + ("list", + Some(r##"Returns a list of YouTube broadcasts that match the API request parameters."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/live-broadcasts_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more liveBroadcast resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, contentDetails, and status."), + Some(r##"The part parameter specifies a comma-separated list of one or more liveBroadcast resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, contentDetails, and status."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("transition", Some("Changes the status of a YouTube live broadcast and initiates any processes associated with the new status. For example, when you transition a broadcast's status to testing, YouTube starts to transmit video to that broadcast's monitor stream. Before calling this method, you should confirm that the value of the status.streamStatus property for the stream bound to your broadcast is active."), + ("transition", + Some(r##"Changes the status of a YouTube live broadcast and initiates any processes associated with the new status. For example, when you transition a broadcast's status to testing, YouTube starts to transmit video to that broadcast's monitor stream. Before calling this method, you should confirm that the value of the status.streamStatus property for the stream bound to your broadcast is active."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/live-broadcasts_transition", vec![ - (Some("broadcast-status"), + (Some(r##"broadcast-status"##), None, - Some("The broadcastStatus parameter identifies the state to which the broadcast is changing. Note that to transition a broadcast to either the testing or live state, the status.streamStatus must be active for the stream that the broadcast is bound to."), + Some(r##"The broadcastStatus parameter identifies the state to which the broadcast is changing. Note that to transition a broadcast to either the testing or live state, the status.streamStatus must be active for the stream that the broadcast is bound to."##), Some(true), Some(false)), - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies the unique ID of the broadcast that is transitioning to another status."), + Some(r##"The id parameter specifies the unique ID of the broadcast that is transitioning to another status."##), Some(true), Some(false)), - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more liveBroadcast resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, contentDetails, and status."), + Some(r##"The part parameter specifies a comma-separated list of one or more liveBroadcast resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, contentDetails, and status."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Updates a broadcast. For example, you could modify the broadcast settings defined in the liveBroadcast resource's contentDetails object."), + ("update", + Some(r##"Updates a broadcast. For example, you could modify the broadcast settings defined in the liveBroadcast resource's contentDetails object."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/live-broadcasts_update", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("live-streams", "methods: 'delete', 'insert', 'list' and 'update'", vec![ - ("delete", Some("Deletes a video stream."), + ("delete", + Some(r##"Deletes a video stream."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/live-streams_delete", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies the YouTube live stream ID for the resource that is being deleted."), + Some(r##"The id parameter specifies the YouTube live stream ID for the resource that is being deleted."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("insert", Some("Creates a video stream. The stream enables you to send your video to YouTube, which can then broadcast the video to your audience."), + ("insert", + Some(r##"Creates a video stream. The stream enables you to send your video to YouTube, which can then broadcast the video to your audience."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/live-streams_insert", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Returns a list of video streams that match the API request parameters."), + ("list", + Some(r##"Returns a list of video streams that match the API request parameters."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/live-streams_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more liveStream resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, cdn, and status."), + Some(r##"The part parameter specifies a comma-separated list of one or more liveStream resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, cdn, and status."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Updates a video stream. If the properties that you want to change cannot be updated, then you need to create a new stream with the proper settings."), + ("update", + Some(r##"Updates a video stream. If the properties that you want to change cannot be updated, then you need to create a new stream with the proper settings."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/live-streams_update", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("playlist-items", "methods: 'delete', 'insert', 'list' and 'update'", vec![ - ("delete", Some("Deletes a playlist item."), + ("delete", + Some(r##"Deletes a playlist item."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/playlist-items_delete", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies the YouTube playlist item ID for the playlist item that is being deleted. In a playlistItem resource, the id property specifies the playlist item's ID."), + Some(r##"The id parameter specifies the YouTube playlist item ID for the playlist item that is being deleted. In a playlistItem resource, the id property specifies the playlist item's ID."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("insert", Some("Adds a resource to a playlist."), + ("insert", + Some(r##"Adds a resource to a playlist."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/playlist-items_insert", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Returns a collection of playlist items that match the API request parameters. You can retrieve all of the playlist items in a specified playlist or retrieve one or more playlist items by their unique IDs."), + ("list", + Some(r##"Returns a collection of playlist items that match the API request parameters. You can retrieve all of the playlist items in a specified playlist or retrieve one or more playlist items by their unique IDs."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/playlist-items_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more playlistItem resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, contentDetails, and status. + Some(r##"The part parameter specifies a comma-separated list of one or more playlistItem resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, contentDetails, and status. - If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a playlistItem resource, the snippet property contains numerous fields, including the title, description, position, and resourceId properties. As such, if you set part=snippet, the API response will contain all of those properties."), + If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a playlistItem resource, the snippet property contains numerous fields, including the title, description, position, and resourceId properties. As such, if you set part=snippet, the API response will contain all of those properties."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Modifies a playlist item. For example, you could update the item's position in the playlist."), + ("update", + Some(r##"Modifies a playlist item. For example, you could update the item's position in the playlist."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/playlist-items_update", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("playlists", "methods: 'delete', 'insert', 'list' and 'update'", vec![ - ("delete", Some("Deletes a playlist."), + ("delete", + Some(r##"Deletes a playlist."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/playlists_delete", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies the YouTube playlist ID for the playlist that is being deleted. In a playlist resource, the id property specifies the playlist's ID."), + Some(r##"The id parameter specifies the YouTube playlist ID for the playlist that is being deleted. In a playlist resource, the id property specifies the playlist's ID."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("insert", Some("Creates a playlist."), + ("insert", + Some(r##"Creates a playlist."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/playlists_insert", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Returns a collection of playlists that match the API request parameters. For example, you can retrieve all playlists that the authenticated user owns, or you can retrieve one or more playlists by their unique IDs."), + ("list", + Some(r##"Returns a collection of playlists that match the API request parameters. For example, you can retrieve all playlists that the authenticated user owns, or you can retrieve one or more playlists by their unique IDs."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/playlists_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more playlist resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, status, and contentDetails. + Some(r##"The part parameter specifies a comma-separated list of one or more playlist resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, status, and contentDetails. - If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a playlist resource, the snippet property contains properties like author, title, description, tags, and timeCreated. As such, if you set part=snippet, the API response will contain all of those properties."), + If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a playlist resource, the snippet property contains properties like author, title, description, tags, and timeCreated. As such, if you set part=snippet, the API response will contain all of those properties."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("update", Some("Modifies a playlist. For example, you could change a playlist's title, description, or privacy status."), + ("update", + Some(r##"Modifies a playlist. For example, you could change a playlist's title, description, or privacy status."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/playlists_update", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("search", "methods: 'list'", vec![ - ("list", Some("Returns a collection of search results that match the query parameters specified in the API request. By default, a search result set identifies matching video, channel, and playlist resources, but you can also configure queries to only retrieve a specific type of resource."), + ("list", + Some(r##"Returns a collection of search results that match the query parameters specified in the API request. By default, a search result set identifies matching video, channel, and playlist resources, but you can also configure queries to only retrieve a specific type of resource."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/search_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more search resource properties that the API response will include. The part names that you can include in the parameter value are id and snippet. + Some(r##"The part parameter specifies a comma-separated list of one or more search resource properties that the API response will include. The part names that you can include in the parameter value are id and snippet. - If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a search result, the snippet property contains other properties that identify the result's title, description, and so forth. If you set part=snippet, the API response will also contain all of those nested properties."), + If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a search result, the snippet property contains other properties that identify the result's title, description, and so forth. If you set part=snippet, the API response will also contain all of those nested properties."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("subscriptions", "methods: 'delete', 'insert' and 'list'", vec![ - ("delete", Some("Deletes a subscription."), + ("delete", + Some(r##"Deletes a subscription."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/subscriptions_delete", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies the YouTube subscription ID for the resource that is being deleted. In a subscription resource, the id property specifies the YouTube subscription ID."), + Some(r##"The id parameter specifies the YouTube subscription ID for the resource that is being deleted. In a subscription resource, the id property specifies the YouTube subscription ID."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("insert", Some("Adds a subscription for the authenticated user's channel."), + ("insert", + Some(r##"Adds a subscription for the authenticated user's channel."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/subscriptions_insert", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Returns subscription resources that match the API request criteria."), + ("list", + Some(r##"Returns subscription resources that match the API request criteria."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/subscriptions_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more subscription resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, and contentDetails. + Some(r##"The part parameter specifies a comma-separated list of one or more subscription resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, and contentDetails. - If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a subscription resource, the snippet property contains other properties, such as a display title for the subscription. If you set part=snippet, the API response will also contain all of those nested properties."), + If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a subscription resource, the snippet property contains other properties, such as a display title for the subscription. If you set part=snippet, the API response will also contain all of those nested properties."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("thumbnails", "methods: 'set'", vec![ - ("set", Some("Uploads a custom video thumbnail to YouTube and sets it for a video."), + ("set", + Some(r##"Uploads a custom video thumbnail to YouTube and sets it for a video."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/thumbnails_set", vec![ - (Some("video-id"), + (Some(r##"video-id"##), None, - Some("The videoId parameter specifies a YouTube video ID for which the custom video thumbnail is being provided."), + Some(r##"The videoId parameter specifies a YouTube video ID for which the custom video thumbnail is being provided."##), Some(true), Some(false)), - (Some("mode"), - Some("u"), - Some("Specify the upload protocol (simple|resumable) and the file to upload"), + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("video-abuse-report-reasons", "methods: 'list'", vec![ - ("list", Some("Returns a list of abuse reasons that can be used for reporting abusive videos."), + ("list", + Some(r##"Returns a list of abuse reasons that can be used for reporting abusive videos."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/video-abuse-report-reasons_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies the videoCategory resource parts that the API response will include. Supported values are id and snippet."), + Some(r##"The part parameter specifies the videoCategory resource parts that the API response will include. Supported values are id and snippet."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("video-categories", "methods: 'list'", vec![ - ("list", Some("Returns a list of categories that can be associated with YouTube videos."), + ("list", + Some(r##"Returns a list of categories that can be associated with YouTube videos."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/video-categories_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies the videoCategory resource parts that the API response will include. Supported values are id and snippet."), + Some(r##"The part parameter specifies the videoCategory resource parts that the API response will include. Supported values are id and snippet."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("videos", "methods: 'delete', 'get-rating', 'insert', 'list', 'rate', 'report-abuse' and 'update'", vec![ - ("delete", Some("Deletes a YouTube video."), + ("delete", + Some(r##"Deletes a YouTube video."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/videos_delete", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies the YouTube video ID for the resource that is being deleted. In a video resource, the id property specifies the video's ID."), + Some(r##"The id parameter specifies the YouTube video ID for the resource that is being deleted. In a video resource, the id property specifies the video's ID."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("get-rating", Some("Retrieves the ratings that the authorized user gave to a list of specified videos."), + ("get-rating", + Some(r##"Retrieves the ratings that the authorized user gave to a list of specified videos."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/videos_get-rating", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies a comma-separated list of the YouTube video ID(s) for the resource(s) for which you are retrieving rating data. In a video resource, the id property specifies the video's ID."), + Some(r##"The id parameter specifies a comma-separated list of the YouTube video ID(s) for the resource(s) for which you are retrieving rating data. In a video resource, the id property specifies the video's ID."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("insert", Some("Uploads a video to YouTube and optionally sets the video's metadata."), + ("insert", + Some(r##"Uploads a video to YouTube and optionally sets the video's metadata."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/videos_insert", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("mode"), - Some("u"), - Some("Specify the upload protocol (simple|resumable) and the file to upload"), + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("list", Some("Returns a list of videos that match the API request parameters."), + ("list", + Some(r##"Returns a list of videos that match the API request parameters."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/videos_list", vec![ - (Some("part"), + (Some(r##"part"##), None, - Some("The part parameter specifies a comma-separated list of one or more video resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, contentDetails, fileDetails, liveStreamingDetails, localizations, player, processingDetails, recordingDetails, statistics, status, suggestions, and topicDetails. + Some(r##"The part parameter specifies a comma-separated list of one or more video resource properties that the API response will include. The part names that you can include in the parameter value are id, snippet, contentDetails, fileDetails, liveStreamingDetails, localizations, player, processingDetails, recordingDetails, statistics, status, suggestions, and topicDetails. - If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a video resource, the snippet property contains the channelId, title, description, tags, and categoryId properties. As such, if you set part=snippet, the API response will contain all of those properties."), + If the parameter identifies a property that contains child properties, the child properties will be included in the response. For example, in a video resource, the snippet property contains the channelId, title, description, tags, and categoryId properties. As such, if you set part=snippet, the API response will contain all of those properties."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), - ("rate", Some("Add a like or dislike rating to a video or remove a rating from a video."), + ("rate", + Some(r##"Add a like or dislike rating to a video or remove a rating from a video."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/videos_rate", vec![ - (Some("id"), + (Some(r##"id"##), None, - Some("The id parameter specifies the YouTube video ID of the video that is being rated or having its rating removed."), + Some(r##"The id parameter specifies the YouTube video ID of the video that is being rated or having its rating removed."##), Some(true), Some(false)), - (Some("rating"), + (Some(r##"rating"##), None, - Some("Specifies the rating to record."), + Some(r##"Specifies the rating to record."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("report-abuse", Some("Report abuse for a video."), + ("report-abuse", + Some(r##"Report abuse for a video."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/videos_report-abuse", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("update", Some("Updates a video's metadata."), + ("update", + Some(r##"Updates a video's metadata."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/videos_update", vec![ - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), - (Some("out"), - Some("o"), - Some("Specify the file into which to write the programs output"), + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), Some(false), Some(false)), ]), ]), ("watermarks", "methods: 'set' and 'unset'", vec![ - ("set", Some("Uploads a watermark image to YouTube and sets it for a channel."), + ("set", + Some(r##"Uploads a watermark image to YouTube and sets it for a channel."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/watermarks_set", vec![ - (Some("channel-id"), + (Some(r##"channel-id"##), None, - Some("The channelId parameter specifies a YouTube channel ID for which the watermark is being provided."), + Some(r##"The channelId parameter specifies a YouTube channel ID for which the watermark is being provided."##), Some(true), Some(false)), - (Some("kv"), - Some("r"), - Some("Set various fields of the request structure"), + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), Some(true), Some(true)), - (Some("mode"), - Some("u"), - Some("Specify the upload protocol (simple|resumable) and the file to upload"), + (Some(r##"mode"##), + Some(r##"u"##), + Some(r##"Specify the upload protocol (simple|resumable) and the file to upload"##), Some(true), Some(true)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), - ("unset", Some("Deletes a watermark."), + ("unset", + Some(r##"Deletes a watermark."##), + "Details at http://byron.github.io/google-apis-rs/google_youtube3_cli/watermarks_unset", vec![ - (Some("channel-id"), + (Some(r##"channel-id"##), None, - Some("The channelId parameter specifies a YouTube channel ID for which the watermark is being unset."), + Some(r##"The channelId parameter specifies a YouTube channel ID for which the watermark is being unset."##), Some(true), Some(false)), - (Some("v"), - Some("p"), - Some("Set various fields of the request structure"), + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), Some(false), Some(true)), ]), @@ -11328,11 +11514,12 @@ fn main() { for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { let mut mcmd = SubCommand::new(main_command_name).about(about); - for &(sub_command_name, ref desc, ref args) in subcommands { + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { let mut scmd = SubCommand::new(sub_command_name); if let &Some(desc) = desc { scmd = scmd.about(desc); } + scmd = scmd.after_help(url_info); for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { let arg_name_str = diff --git a/gen/youtube3/cargo.toml b/gen/youtube3/cargo.toml index 16da8ddc46..8b84f82153 100644 --- a/gen/youtube3/cargo.toml +++ b/gen/youtube3/cargo.toml @@ -15,9 +15,10 @@ keywords = ["youtube", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/youtube3/src/cmn.rs b/gen/youtube3/src/cmn.rs index b65c5301bb..908bef39dc 100644 --- a/gen/youtube3/src/cmn.rs +++ b/gen/youtube3/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -250,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -293,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -589,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -625,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/youtube3/src/lib.rs b/gen/youtube3/src/lib.rs index 392e7ad07c..04dd708298 100644 --- a/gen/youtube3/src/lib.rs +++ b/gen/youtube3/src/lib.rs @@ -255,6 +255,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -7216,7 +7217,7 @@ impl<'a, C, A> I18nLanguageListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -7426,6 +7427,7 @@ impl<'a, C, A> ChannelBannerInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, ChannelBannerResource)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -7467,11 +7469,20 @@ impl<'a, C, A> ChannelBannerInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -7847,7 +7858,7 @@ impl<'a, C, A> ChannelSectionListCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8104,6 +8115,7 @@ impl<'a, C, A> ChannelSectionInsertCall<'a, C, A> where C: BorrowMut<hyper::Clie /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ChannelSection)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8144,11 +8156,20 @@ impl<'a, C, A> ChannelSectionInsertCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8415,7 +8436,7 @@ impl<'a, C, A> ChannelSectionDeleteCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -8624,6 +8645,7 @@ impl<'a, C, A> ChannelSectionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clie /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, ChannelSection)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -8661,11 +8683,20 @@ impl<'a, C, A> ChannelSectionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -8948,7 +8979,7 @@ impl<'a, C, A> GuideCategoryListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9188,6 +9219,7 @@ impl<'a, C, A> PlaylistInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Playlist)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -9228,11 +9260,20 @@ impl<'a, C, A> PlaylistInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -9553,7 +9594,7 @@ impl<'a, C, A> PlaylistListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -9843,7 +9884,7 @@ impl<'a, C, A> PlaylistDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10052,6 +10093,7 @@ impl<'a, C, A> PlaylistUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Playlist)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10089,11 +10131,20 @@ impl<'a, C, A> PlaylistUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10362,7 +10413,7 @@ impl<'a, C, A> ThumbnailSetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -10663,6 +10714,7 @@ impl<'a, C, A> VideoReportAbuseCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<hyper::client::Response> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -10695,11 +10747,20 @@ impl<'a, C, A> VideoReportAbuseCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -10993,7 +11054,7 @@ impl<'a, C, A> VideoListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11308,7 +11369,7 @@ impl<'a, C, A> VideoRateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11537,7 +11598,7 @@ impl<'a, C, A> VideoGetRatingCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11765,7 +11826,7 @@ impl<'a, C, A> VideoDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -11994,6 +12055,7 @@ impl<'a, C, A> VideoUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Video)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12031,11 +12093,20 @@ impl<'a, C, A> VideoUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12337,6 +12408,7 @@ impl<'a, C, A> VideoInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, Video)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12394,11 +12466,20 @@ impl<'a, C, A> VideoInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -12802,6 +12883,7 @@ impl<'a, C, A> SubscriptionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Subscription)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -12836,11 +12918,20 @@ impl<'a, C, A> SubscriptionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -13150,7 +13241,7 @@ impl<'a, C, A> SubscriptionListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13448,7 +13539,7 @@ impl<'a, C, A> SubscriptionDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -13819,7 +13910,7 @@ impl<'a, C, A> SearchListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oa if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14276,7 +14367,7 @@ impl<'a, C, A> I18nRegionListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14560,7 +14651,7 @@ impl<'a, C, A> CommentThreadListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -14843,6 +14934,7 @@ impl<'a, C, A> CommentThreadUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CommentThread)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -14877,11 +14969,20 @@ impl<'a, C, A> CommentThreadUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15117,6 +15218,7 @@ impl<'a, C, A> CommentThreadInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, CommentThread)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15154,11 +15256,20 @@ impl<'a, C, A> CommentThreadInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15408,6 +15519,7 @@ impl<'a, C, A> LiveStreamUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LiveStream)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -15448,11 +15560,20 @@ impl<'a, C, A> LiveStreamUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -15730,7 +15851,7 @@ impl<'a, C, A> LiveStreamDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16002,7 +16123,7 @@ impl<'a, C, A> LiveStreamListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -16272,6 +16393,7 @@ impl<'a, C, A> LiveStreamInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LiveStream)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -16312,11 +16434,20 @@ impl<'a, C, A> LiveStreamInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -16574,6 +16705,7 @@ impl<'a, C, A> CommentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Comment)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -16608,11 +16740,20 @@ impl<'a, C, A> CommentInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -16861,7 +17002,7 @@ impl<'a, C, A> CommentSetModerationStatuCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17084,7 +17225,7 @@ impl<'a, C, A> CommentDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17325,7 +17466,7 @@ impl<'a, C, A> CommentListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -17575,6 +17716,7 @@ impl<'a, C, A> CommentUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Comment)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -17609,11 +17751,20 @@ impl<'a, C, A> CommentUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -17855,7 +18006,7 @@ impl<'a, C, A> CommentMarkAsSpamCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18055,6 +18206,7 @@ impl<'a, C, A> ChannelUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Channel)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -18092,11 +18244,20 @@ impl<'a, C, A> ChannelUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -18419,7 +18580,7 @@ impl<'a, C, A> ChannelListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18735,7 +18896,7 @@ impl<'a, C, A> VideoAbuseReportReasonListCall<'a, C, A> where C: BorrowMut<hyper if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -18959,6 +19120,7 @@ impl<'a, C, A> PlaylistItemInsertCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PlaylistItem)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -18996,11 +19158,20 @@ impl<'a, C, A> PlaylistItemInsertCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -19253,7 +19424,7 @@ impl<'a, C, A> PlaylistItemDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19506,7 +19677,7 @@ impl<'a, C, A> PlaylistItemListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -19769,6 +19940,7 @@ impl<'a, C, A> PlaylistItemUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, PlaylistItem)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -19803,11 +19975,20 @@ impl<'a, C, A> PlaylistItemUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -20034,6 +20215,7 @@ impl<'a, C, A> WatermarkSetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<hyper::client::Response> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -20075,11 +20257,20 @@ impl<'a, C, A> WatermarkSetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -20415,7 +20606,7 @@ impl<'a, C, A> WatermarkUnsetCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -20670,7 +20861,7 @@ impl<'a, C, A> LiveBroadcastControlCall<'a, C, A> where C: BorrowMut<hyper::Clie if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -20947,6 +21138,7 @@ impl<'a, C, A> LiveBroadcastUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LiveBroadcast)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -20987,11 +21179,20 @@ impl<'a, C, A> LiveBroadcastUpdateCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -21260,6 +21461,7 @@ impl<'a, C, A> LiveBroadcastInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, LiveBroadcast)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -21300,11 +21502,20 @@ impl<'a, C, A> LiveBroadcastInsertCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -21623,7 +21834,7 @@ impl<'a, C, A> LiveBroadcastListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -21909,7 +22120,7 @@ impl<'a, C, A> LiveBroadcastDeleteCall<'a, C, A> where C: BorrowMut<hyper::Clien if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -22164,7 +22375,7 @@ impl<'a, C, A> LiveBroadcastTransitionCall<'a, C, A> where C: BorrowMut<hyper::C if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -22459,7 +22670,7 @@ impl<'a, C, A> LiveBroadcastBindCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -22727,7 +22938,7 @@ impl<'a, C, A> CaptionDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -22930,6 +23141,7 @@ impl<'a, C, A> CaptionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, Caption)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -22981,11 +23193,20 @@ impl<'a, C, A> CaptionInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -23374,7 +23595,7 @@ impl<'a, C, A> CaptionListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -23671,7 +23892,7 @@ impl<'a, C, A> CaptionDownloadCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -23888,6 +24109,7 @@ impl<'a, C, A> CaptionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: /// Perform the operation you have build so far. fn doit<RS>(mut self, mut reader: RS, reader_mime_type: mime::Mime, protocol: &'static str) -> Result<(hyper::client::Response, Caption)> where RS: ReadSeek { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -23939,11 +24161,20 @@ impl<'a, C, A> CaptionUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -24335,7 +24566,7 @@ impl<'a, C, A> VideoCategoryListCall<'a, C, A> where C: BorrowMut<hyper::Client> if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -24632,7 +24863,7 @@ impl<'a, C, A> ActivityListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -24905,6 +25136,7 @@ impl<'a, C, A> ActivityInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Activity)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -24939,11 +25171,20 @@ impl<'a, C, A> ActivityInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); diff --git a/gen/youtubeanalytics1-cli/Cargo.toml b/gen/youtubeanalytics1-cli/Cargo.toml index 35cc0a4552..1cf63fda58 100644 --- a/gen/youtubeanalytics1-cli/Cargo.toml +++ b/gen/youtubeanalytics1-cli/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-youtubeanalytics1-cli" -version = "0.1.0+20150304" +version = "0.2.0+20150304" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with YouTube Analytics (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/youtubeanalytics1-cli" @@ -17,15 +17,14 @@ keywords = ["youtubeAnalytics", "google", "cli"] name = "youtubeanalytics1" [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" -docopt = "*" -docopt_macros = "*" -rustc-serialize = "*" +strsim = "*" yup-hyper-mock = "*" serde = ">= 0.3.0" serde_macros = "*" +clap = "*" [dependencies.google-youtubeanalytics1] path = "../youtubeanalytics1" diff --git a/gen/youtubeanalytics1-cli/README.md b/gen/youtubeanalytics1-cli/README.md index f0b53a7892..9ef0f9e488 100644 --- a/gen/youtubeanalytics1-cli/README.md +++ b/gen/youtubeanalytics1-cli/README.md @@ -10,30 +10,36 @@ capabilities. Errors will be printed to standard error, and cause the program's If data-structures are requested, these will be returned as pretty-printed JSON, to be useful as input to other tools. +Everything else about the *YouTube Analytics* API can be found at the +[official documentation site](http://developers.google.com/youtube/analytics/). + # Usage -This documentation was generated from the *YouTube Analytics* API at revision *20150304*. The CLI is at version *0.1.0*. +This documentation was generated from the *YouTube Analytics* API at revision *20150304*. The CLI is at version *0.2.0*. ```bash - youtubeanalytics1 [options] batch-report-definitions list <on-behalf-of-content-owner> [-p <v>...] [-o <out>] - youtubeanalytics1 [options] batch-reports list <batch-report-definition-id> <on-behalf-of-content-owner> [-p <v>...] [-o <out>] - youtubeanalytics1 [options] group-items delete <id> [-p <v>...] - youtubeanalytics1 [options] group-items insert -r <kv>... [-p <v>...] [-o <out>] - youtubeanalytics1 [options] group-items list <group-id> [-p <v>...] [-o <out>] - youtubeanalytics1 [options] groups delete <id> [-p <v>...] - youtubeanalytics1 [options] groups insert -r <kv>... [-p <v>...] [-o <out>] - youtubeanalytics1 [options] groups list [-p <v>...] [-o <out>] - youtubeanalytics1 [options] groups update -r <kv>... [-p <v>...] [-o <out>] - youtubeanalytics1 [options] reports query <ids> <start-date> <end-date> <metrics> [-p <v>...] [-o <out>] +youtubeanalytics1 [options] + batch-report-definitions + list <on-behalf-of-content-owner> [-p <v>]... [-o <out>] + batch-reports + list <batch-report-definition-id> <on-behalf-of-content-owner> [-p <v>]... [-o <out>] + group-items + delete <id> [-p <v>]... + insert (-r <kv>)... [-p <v>]... [-o <out>] + list <group-id> [-p <v>]... [-o <out>] + groups + delete <id> [-p <v>]... + insert (-r <kv>)... [-p <v>]... [-o <out>] + list [-p <v>]... [-o <out>] + update (-r <kv>)... [-p <v>]... [-o <out>] + reports + query <ids> <start-date> <end-date> <metrics> [-p <v>]... [-o <out>] youtubeanalytics1 --help -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_youtubeanalytics1_cli/index.html - Configuration: - --scope <url> + [--scope <url>]... Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. + requires the user to grant this application permission to use it. If unset, it defaults to the shortest scope url for a particular method. --config-dir <folder> A directory into which we will store our persistent data. Defaults to diff --git a/gen/youtubeanalytics1-cli/mkdocs.yml b/gen/youtubeanalytics1-cli/mkdocs.yml index b68009e409..414b7f4f4b 100644 --- a/gen/youtubeanalytics1-cli/mkdocs.yml +++ b/gen/youtubeanalytics1-cli/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: YouTube Analytics v0.1.0+20150304 +site_name: YouTube Analytics v0.2.0+20150304 site_url: http://byron.github.io/google-apis-rs/google-youtubeanalytics1-cli site_description: Write integrating applications with bcore diff --git a/gen/youtubeanalytics1-cli/src/cmn.rs b/gen/youtubeanalytics1-cli/src/cmn.rs index 4ba65df643..3335e7b6bd 100644 --- a/gen/youtubeanalytics1-cli/src/cmn.rs +++ b/gen/youtubeanalytics1-cli/src/cmn.rs @@ -1,8 +1,10 @@ // COPY OF 'src/rust/cli/cmn.rs' // DO NOT EDIT use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token}; -use rustc_serialize::json; +use serde::json; use mime::Mime; +use clap::{App, SubCommand}; +use strsim; use std::fs; use std::env; @@ -17,6 +19,74 @@ use std::default::Default; const FIELD_SEP: char = '.'; +// Based on @erickt user comment. Thanks for the idea ! +// Remove all keys whose values are null from given value (changed in place) +pub fn remove_json_null_values(value: &mut json::value::Value) { + match *value { + json::value::Value::Object(ref mut map) => { + let mut for_removal = Vec::new(); + + for (key, mut value) in map.iter_mut() { + if value.is_null() { + for_removal.push(key.clone()); + } else { + remove_json_null_values(&mut value); + } + } + + for key in &for_removal { + map.remove(key); + } + } + _ => {} + } +} + +fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> { + + let mut candidate: Option<(f64, &str)> = None; + for pv in possible_values { + let confidence = strsim::jaro_winkler(v, pv); + if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) { + candidate = Some((confidence, pv)); + } + } + match candidate { + None => None, + Some((_, candidate)) => Some(candidate), + } +} + +pub enum CallType { + Upload(UploadProtocol), + Standard, +} + +arg_enum!{ + pub enum UploadProtocol { + Simple, + Resumable + } +} + +impl AsRef<str> for UploadProtocol { + fn as_ref(&self) -> &str { + match *self { + UploadProtocol::Simple => "simple", + UploadProtocol::Resumable => "resumable" + } + } +} + +impl AsRef<str> for CallType { + fn as_ref(&self) -> &str { + match *self { + CallType::Upload(ref proto) => proto.as_ref(), + CallType::Standard => "standard-request" + } + } +} + #[derive(Clone, Default)] pub struct FieldCursor(Vec<String>); @@ -88,6 +158,49 @@ impl FieldCursor { Ok(()) } + pub fn did_you_mean(value: &str, possible_values: &[&str]) -> Option<String> { + if value.len() == 0 { + return None + } + + let mut last_c = FIELD_SEP; + + let mut field = String::new(); + let mut output = String::new(); + + let push_field = |fs: &mut String, f: &mut String| { + if f.len() > 0 { + fs.push_str( + match did_you_mean(&f, possible_values) { + Some(candidate) => candidate, + None => &f, + }); + f.truncate(0); + } + }; + + for (cid, c) in value.chars().enumerate() { + if c == FIELD_SEP { + if last_c != FIELD_SEP { + push_field(&mut output, &mut field); + } + output.push(c); + } else { + field.push(c); + } + + last_c = c; + } + + push_field(&mut output, &mut field); + + if &output == value { + None + } else { + Some(output) + } + } + pub fn num_fields(&self) -> usize { self.0.len() } @@ -112,6 +225,17 @@ pub fn parse_kv_arg<'a>(kv: &'a str, err: &mut InvalidOptionsError, for_hashmap: } } +pub fn calltype_from_str(name: &str, valid_protocols: Vec<String>, err: &mut InvalidOptionsError) -> CallType { + CallType::Upload( + match UploadProtocol::from_str(name) { + Ok(up) => up, + Err(msg) => { + err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols)); + UploadProtocol::Simple + } + }) +} + pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> Option<fs::File> { match fs::File::open(file_path) { Ok(f) => Some(f), @@ -132,13 +256,14 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option } } -// May panic if we can't open the file - this is anticipated, we can't currently communicate this -// kind of error: TODO: fix this architecture :) -pub fn writer_from_opts(flag: bool, arg: &str) -> Box<Write> { - if !flag || arg == "-" { - Box::new(stdout()) - } else { - Box::new(fs::OpenOptions::new().create(true).write(true).open(arg).unwrap()) +pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<Write>, io::Error> { + let f = arg.unwrap_or("-"); + match f { + "-" => Ok(Box::new(stdout())), + _ => match fs::OpenOptions::new().create(true).write(true).open(f) { + Ok(f) => Ok(Box::new(f)), + Err(io_err) => Err(io_err), + } } } @@ -151,7 +276,7 @@ pub fn arg_from_str<T>(arg: &str, err: &mut InvalidOptionsError, match FromStr::from_str(arg) { Err(perr) => { err.issues.push( - CLIError::ParseError((arg_name, arg_type, arg.to_string(), format!("{}", perr))) + CLIError::ParseError(arg_name, arg_type, arg.to_string(), format!("{}", perr)) ); Default::default() }, @@ -171,49 +296,47 @@ impl JsonTokenStorage { } impl TokenStorage for JsonTokenStorage { - type Error = io::Error; + type Error = json::Error; // NOTE: logging might be interesting, currently we swallow all errors - fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Option<io::Error> { + fn set(&mut self, scope_hash: u64, _: &Vec<&str>, token: Option<Token>) -> Result<(), json::Error> { match token { None => { match fs::remove_file(self.path(scope_hash)) { Err(err) => match err.kind() { - io::ErrorKind::NotFound => None, - _ => Some(err) + io::ErrorKind::NotFound => Ok(()), + _ => Err(json::Error::IoError(err)) }, - Ok(_) => None + Ok(_) => Ok(()), } } Some(token) => { - let json_token = json::encode(&token).unwrap(); match fs::OpenOptions::new().create(true).write(true).open(&self.path(scope_hash)) { Ok(mut f) => { - match f.write(json_token.as_bytes()) { - Ok(_) => None, - Err(io_err) => Some(io_err), + match json::to_writer_pretty(&mut f, &token) { + Ok(_) => Ok(()), + Err(io_err) => Err(json::Error::IoError(io_err)), } }, - Err(io_err) => Some(io_err) + Err(io_err) => Err(json::Error::IoError(io_err)) } } } } - fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, io::Error> { + fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, json::Error> { match fs::File::open(&self.path(scope_hash)) { Ok(mut f) => { - let mut json_string = String::new(); - match f.read_to_string(&mut json_string) { - Ok(_) => Ok(Some(json::decode::<Token>(&json_string).unwrap())), - Err(io_err) => Err(io_err), + match json::de::from_reader(f) { + Ok(token) => Ok(Some(token)), + Err(err) => Err(err), } }, Err(io_err) => { match io_err.kind() { io::ErrorKind::NotFound => Ok(None), - _ => Err(io_err) + _ => Err(json::Error::IoError(io_err)) } } } @@ -223,7 +346,7 @@ impl TokenStorage for JsonTokenStorage { #[derive(Debug)] pub enum ApplicationSecretError { - DecoderError((String, json::DecoderError)), + DecoderError((String, json::Error)), FormatError(String), } @@ -231,10 +354,10 @@ impl fmt::Display for ApplicationSecretError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ApplicationSecretError::DecoderError((ref path, ref err)) - => writeln!(f, "Could not decode file at '{}' with error: {}", + => writeln!(f, "Could not decode file at '{}' with error: {}.", path, err), ApplicationSecretError::FormatError(ref path) - => writeln!(f, "'installed' field is unset in secret file at '{}'", + => writeln!(f, "'installed' field is unset in secret file at '{}'.", path), } } @@ -253,15 +376,15 @@ impl fmt::Display for ConfigurationError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) - => writeln!(f, "Directory '{}' could not be created with error: {}", dir, err), + => writeln!(f, "Directory '{}' could not be created with error: {}.", dir, err), ConfigurationError::DirectoryUnset - => writeln!(f, "--config-dir was unset or empty"), + => writeln!(f, "--config-dir was unset or empty."), ConfigurationError::HomeExpansionFailed(ref dir) - => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'", dir), + => writeln!(f, "Couldn't find HOME directory of current user, failed to expand '{}'.", dir), ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err), ConfigurationError::IOError((ref path, ref err)) - => writeln!(f, "IO operation failed on path '{}' with error: {}", path, err), + => writeln!(f, "IO operation failed on path '{}' with error: {}.", path, err), } } } @@ -276,9 +399,9 @@ impl fmt::Display for InputError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { InputError::IOError((ref file_path, ref io_err)) - => writeln!(f, "Failed to open '{}' for reading with error: {}", file_path, io_err), + => writeln!(f, "Failed to open '{}' for reading with error: {}.", file_path, io_err), InputError::Mime(ref mime) - => writeln!(f, "'{}' is not a known mime-type", mime), + => writeln!(f, "'{}' is not a known mime-type.", mime), } } } @@ -287,7 +410,7 @@ impl fmt::Display for InputError { pub enum FieldError { PopOnEmpty(String), TrailingFieldSep(String), - Unknown(String), + Unknown(String, Option<String>, Option<String>), Empty, } @@ -296,13 +419,26 @@ impl fmt::Display for FieldError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { FieldError::PopOnEmpty(ref field) - => writeln!(f, "'{}': Cannot move up on empty field cursor", field), + => writeln!(f, "'{}': Cannot move up on empty field cursor.", field), FieldError::TrailingFieldSep(ref field) - => writeln!(f, "'{}': Single field separator may not be last character", field), - FieldError::Unknown(ref field) - => writeln!(f, "Field '{}' does not exist", field), + => writeln!(f, "'{}': Single field separator may not be last character.", field), + FieldError::Unknown(ref field, ref suggestion, ref value) => { + let suffix = + match *suggestion { + Some(ref s) => { + let kv = + match *value { + Some(ref v) => format!("{}={}", s, v), + None => s.clone(), + }; + format!(" Did you mean '{}' ?", kv) + }, + None => String::new(), + }; + writeln!(f, "Field '{}' does not exist.{}", field, suffix) + }, FieldError::Empty - => writeln!(f, "Field names must not be empty"), + => writeln!(f, "Field names must not be empty."), } } } @@ -311,11 +447,14 @@ impl fmt::Display for FieldError { #[derive(Debug)] pub enum CLIError { Configuration(ConfigurationError), - ParseError((&'static str, &'static str, String, String)), - UnknownParameter(String), + ParseError(&'static str, &'static str, String, String), + UnknownParameter(String, Vec<&'static str>), + InvalidUploadProtocol(String, Vec<String>), InvalidKeyValueSyntax(String, bool), Input(InputError), Field(FieldError), + MissingCommandError, + MissingMethodError(String), } impl fmt::Display for CLIError { @@ -324,15 +463,25 @@ impl fmt::Display for CLIError { CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err), CLIError::Input(ref err) => write!(f, "Input -> {}", err), CLIError::Field(ref err) => write!(f, "Field -> {}", err), - CLIError::ParseError((arg_name, type_name, ref value, ref err_desc)) - => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}", + CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) + => writeln!(f, "'{}' is not a valid upload protocol. Choose from one of {}.", proto_name, valid_names.connect(", ")), + CLIError::ParseError(arg_name, type_name, ref value, ref err_desc) + => writeln!(f, "Failed to parse argument '{}' with value '{}' as {} with error: {}.", arg_name, value, type_name, err_desc), - CLIError::UnknownParameter(ref param_name) - => writeln!(f, "Parameter '{}' is unknown.", param_name), + CLIError::UnknownParameter(ref param_name, ref possible_values) => { + let mut suffix = + match did_you_mean(param_name, &possible_values) { + Some(v) => format!(" Did you mean '{}' ?", v), + None => String::new(), + }; + write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix) + }, CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => { let hashmap_info = if is_hashmap { "hashmap " } else { "" }; - writeln!(f, "'{}' does not match {}pattern <key>=<value>", kv, hashmap_info) + writeln!(f, "'{}' does not match {}pattern <key>=<value>.", kv, hashmap_info) }, + CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."), + CLIError::MissingMethodError(ref cmd) => writeln!(f, "Please specify the method to call on the '{}' command.", cmd), } } } @@ -399,7 +548,7 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> { pub fn application_secret_from_directory(dir: &str, secret_basename: &str, - json_app_secret: &str) + json_console_secret: &str) -> Result<ApplicationSecret, CLIError> { let secret_path = Path::new(dir).join(secret_basename); let secret_str = || secret_path.as_path().to_str().unwrap().to_string(); @@ -418,7 +567,10 @@ pub fn application_secret_from_directory(dir: &str, err = match fs::OpenOptions::new().create(true).write(true).open(&secret_path) { Err(cfe) => cfe, Ok(mut f) => { - match f.write(json_app_secret.as_bytes()) { + // Assure we convert 'ugly' json string into pretty one + let console_secret: ConsoleApplicationSecret + = json::from_str(json_console_secret).unwrap(); + match json::to_writer_pretty(&mut f, &console_secret) { Err(io_err) => io_err, Ok(_) => continue, } @@ -429,23 +581,24 @@ pub fn application_secret_from_directory(dir: &str, return secret_io_error(err) }, Ok(mut f) => { - let mut json_encoded_secret = String::new(); - if let Err(io_err) = f.read_to_string(&mut json_encoded_secret) { - return secret_io_error(io_err) - } - match json::decode::<ConsoleApplicationSecret>(&json_encoded_secret) { - Err(json_decode_error) => return Err(CLIError::Configuration( - ConfigurationError::Secret(ApplicationSecretError::DecoderError( - (secret_str(), json_decode_error) + match json::de::from_reader::<_, ConsoleApplicationSecret>(f) { + Err(json::Error::IoError(err)) => + return secret_io_error(err), + Err(json_err) => + return Err(CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::DecoderError( + (secret_str(), json_err) )))), - Ok(console_secret) => match console_secret.installed { - Some(secret) => return Ok(secret), - None => return Err( - CLIError::Configuration( - ConfigurationError::Secret( - ApplicationSecretError::FormatError(secret_str()) - ))) - }, + Ok(console_secret) => + match console_secret.installed { + Some(secret) => return Ok(secret), + None => return Err( + CLIError::Configuration( + ConfigurationError::Secret( + ApplicationSecretError::FormatError(secret_str()) + ))) + }, } } } diff --git a/gen/youtubeanalytics1-cli/src/main.rs b/gen/youtubeanalytics1-cli/src/main.rs index 424f8af2a6..065c6311ee 100644 --- a/gen/youtubeanalytics1-cli/src/main.rs +++ b/gen/youtubeanalytics1-cli/src/main.rs @@ -2,217 +2,201 @@ // This file was generated automatically from 'src/mako/cli/main.rs.mako' // DO NOT EDIT ! #![feature(plugin, exit_status)] -#![plugin(docopt_macros)] #![allow(unused_variables, unused_imports, dead_code, unused_mut)] -extern crate docopt; +#[macro_use] +extern crate clap; extern crate yup_oauth2 as oauth2; extern crate yup_hyper_mock as mock; -extern crate rustc_serialize; extern crate serde; extern crate hyper; extern crate mime; +extern crate strsim; extern crate google_youtubeanalytics1 as api; use std::env; use std::io::{self, Write}; - -docopt!(Options derive Debug, " -Usage: - youtubeanalytics1 [options] batch-report-definitions list <on-behalf-of-content-owner> [-p <v>...] [-o <out>] - youtubeanalytics1 [options] batch-reports list <batch-report-definition-id> <on-behalf-of-content-owner> [-p <v>...] [-o <out>] - youtubeanalytics1 [options] group-items delete <id> [-p <v>...] - youtubeanalytics1 [options] group-items insert -r <kv>... [-p <v>...] [-o <out>] - youtubeanalytics1 [options] group-items list <group-id> [-p <v>...] [-o <out>] - youtubeanalytics1 [options] groups delete <id> [-p <v>...] - youtubeanalytics1 [options] groups insert -r <kv>... [-p <v>...] [-o <out>] - youtubeanalytics1 [options] groups list [-p <v>...] [-o <out>] - youtubeanalytics1 [options] groups update -r <kv>... [-p <v>...] [-o <out>] - youtubeanalytics1 [options] reports query <ids> <start-date> <end-date> <metrics> [-p <v>...] [-o <out>] - youtubeanalytics1 --help - -All documentation details can be found at -http://byron.github.io/google-apis-rs/google_youtubeanalytics1_cli/index.html - -Configuration: - --scope <url> - Specify the authentication a method should be executed in. Each scope - requires the user to grant this application permission to use it. - If unset, it defaults to the shortest scope url for a particular method. - --config-dir <folder> - A directory into which we will store our persistent data. Defaults to - a user-writable directory that we will create during the first invocation. - [default: ~/.google-service-cli] - --debug - Output all server communication to standard error. `tx` and `rx` are placed - into the same stream. - --debug-auth - Output all communication related to authentication to standard error. `tx` - and `rx` are placed into the same stream. -"); +use clap::{App, SubCommand, Arg}; mod cmn; + use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg, - input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError}; + input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol, + calltype_from_str, remove_json_null_values}; use std::default::Default; use std::str::FromStr; use oauth2::{Authenticator, DefaultAuthenticatorDelegate}; -use rustc_serialize::json; +use serde::json; +use clap::ArgMatches; -struct Engine { - opt: Options, +enum DoitError { + IoError(String, io::Error), + ApiError(api::Error), +} + +struct Engine<'n, 'a> { + opt: ArgMatches<'n, 'a>, hub: api::YouTubeAnalytics<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>, + gp: Vec<&'static str>, + gpm: Vec<(&'static str, &'static str)>, } -impl Engine { - fn _batch_report_definitions_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.batch_report_definitions().list(&self.opt.arg_on_behalf_of_content_owner); - for parg in self.opt.arg_v.iter() { +impl<'n, 'a> Engine<'n, 'a> { + fn _batch_report_definitions_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.batch_report_definitions().list(opt.value_of("on-behalf-of-content-owner").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _batch_reports_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.batch_reports().list(&self.opt.arg_batch_report_definition_id, &self.opt.arg_on_behalf_of_content_owner); - for parg in self.opt.arg_v.iter() { + fn _batch_reports_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.batch_reports().list(opt.value_of("batch-report-definition-id").unwrap_or(""), opt.value_of("on-behalf-of-content-owner").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &[] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _group_items_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.group_items().delete(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _group_items_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.group_items().delete(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _group_items_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _group_items_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::GroupItem::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -256,159 +240,167 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["etag", "group-id", "id", "kind", "resource"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.group_items().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _group_items_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.group_items().list(&self.opt.arg_group_id); - for parg in self.opt.arg_v.iter() { + fn _group_items_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.group_items().list(opt.value_of("group-id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _groups_delete(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.groups().delete(&self.opt.arg_id); - for parg in self.opt.arg_v.iter() { + fn _groups_delete(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.groups().delete(opt.value_of("id").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok(mut response) => { - None + Ok(()) } } } } - fn _groups_insert(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _groups_insert(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Group::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -464,61 +456,66 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["content-details", "etag", "id", "item-count", "item-type", "kind", "published-at", "snippet", "title"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.groups().insert(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _groups_list(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _groups_list(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut call = self.hub.groups().list(); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "on-behalf-of-content-owner" => { @@ -530,52 +527,56 @@ impl Engine { "id" => { call = call.id(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner", "mine", "id"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _groups_update(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { + fn _groups_update(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { let mut request = api::Group::default(); let mut field_cursor = FieldCursor::default(); - for kvarg in self.opt.arg_kv.iter() { + for kvarg in opt.values_of("kv").unwrap_or(Vec::new()).iter() { let last_errc = err.issues.len(); let (key, value) = parse_kv_arg(&*kvarg, err, false); let mut temp_cursor = field_cursor.clone(); @@ -631,61 +632,66 @@ impl Engine { request.id = Some(value.unwrap_or("").to_string()); }, _ => { - err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string()))); + let suggestion = FieldCursor::did_you_mean(key, &vec!["content-details", "etag", "id", "item-count", "item-type", "kind", "published-at", "snippet", "title"]); + err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string())))); } } } let mut call = self.hub.groups().update(request); - for parg in self.opt.arg_v.iter() { + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "on-behalf-of-content-owner" => { call = call.on_behalf_of_content_owner(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["on-behalf-of-content-owner"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _reports_query(&self, dry_run: bool, err: &mut InvalidOptionsError) - -> Option<api::Error> { - let mut call = self.hub.reports().query(&self.opt.arg_ids, &self.opt.arg_start_date, &self.opt.arg_end_date, &self.opt.arg_metrics); - for parg in self.opt.arg_v.iter() { + fn _reports_query(&self, opt: &ArgMatches<'n, 'a>, dry_run: bool, err: &mut InvalidOptionsError) + -> Result<(), DoitError> { + let mut call = self.hub.reports().query(opt.value_of("ids").unwrap_or(""), opt.value_of("start-date").unwrap_or(""), opt.value_of("end-date").unwrap_or(""), opt.value_of("metrics").unwrap_or("")); + for parg in opt.values_of("v").unwrap_or(Vec::new()).iter() { let (key, value) = parse_kv_arg(&*parg, err, false); match key { "start-index" => { @@ -706,111 +712,145 @@ impl Engine { "currency" => { call = call.currency(value.unwrap_or("")); }, - "alt" - |"fields" - |"key" - |"oauth-token" - |"pretty-print" - |"quota-user" - |"user-ip" => { - let map = [ - ("oauth-token", "oauth_token"), - ("pretty-print", "prettyPrint"), - ("quota-user", "quotaUser"), - ("user-ip", "userIp"), - ]; - call = call.param(map.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")) - }, - _ => err.issues.push(CLIError::UnknownParameter(key.to_string())), + _ => { + let mut found = false; + for param in &self.gp { + if key == *param { + found = true; + call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset")); + break; + } + } + if !found { + err.issues.push(CLIError::UnknownParameter(key.to_string(), + Vec::new() + &self.gp + &["sort", "max-results", "dimensions", "start-index", "currency", "filters"] + )); + } + } } } - let protocol = "standard-request"; + let protocol = CallType::Standard; if dry_run { - None + Ok(()) } else { assert!(err.issues.len() == 0); - if self.opt.flag_scope.len() > 0 { - call = call.add_scope(&self.opt.flag_scope); + for scope in self.opt.values_of("url").unwrap_or(Vec::new()).iter() { + call = call.add_scope(scope); } - let mut ostream = writer_from_opts(self.opt.flag_o, &self.opt.arg_out); + let mut ostream = match writer_from_opts(opt.value_of("out")) { + Ok(mut f) => f, + Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)), + }; match match protocol { - "standard-request" => call.doit(), - _ => unreachable!(), + CallType::Standard => call.doit(), + _ => unreachable!() } { - Err(api_err) => Some(api_err), + Err(api_err) => Err(DoitError::ApiError(api_err)), Ok((mut response, output_schema)) => { - serde::json::to_writer_pretty(&mut ostream, &output_schema).unwrap(); - None + let mut value = json::value::to_value(&output_schema); + remove_json_null_values(&mut value); + serde::json::to_writer_pretty(&mut ostream, &value).unwrap(); + Ok(()) } } } } - fn _doit(&self, dry_run: bool) -> (Option<api::Error>, Option<InvalidOptionsError>) { + fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> { let mut err = InvalidOptionsError::new(); - let mut call_result: Option<api::Error>; + let mut call_result: Result<(), DoitError> = Ok(()); let mut err_opt: Option<InvalidOptionsError> = None; - - if self.opt.cmd_batch_report_definitions { - if self.opt.cmd_list { - call_result = self._batch_report_definitions_list(dry_run, &mut err); - } else { - unreachable!(); + match self.opt.subcommand() { + ("batch-report-definitions", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._batch_report_definitions_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("batch-report-definitions".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("batch-reports", Some(opt)) => { + match opt.subcommand() { + ("list", Some(opt)) => { + call_result = self._batch_reports_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("batch-reports".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("group-items", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._group_items_delete(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._group_items_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._group_items_list(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("group-items".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("groups", Some(opt)) => { + match opt.subcommand() { + ("delete", Some(opt)) => { + call_result = self._groups_delete(opt, dry_run, &mut err); + }, + ("insert", Some(opt)) => { + call_result = self._groups_insert(opt, dry_run, &mut err); + }, + ("list", Some(opt)) => { + call_result = self._groups_list(opt, dry_run, &mut err); + }, + ("update", Some(opt)) => { + call_result = self._groups_update(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("groups".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + ("reports", Some(opt)) => { + match opt.subcommand() { + ("query", Some(opt)) => { + call_result = self._reports_query(opt, dry_run, &mut err); + }, + _ => { + err.issues.push(CLIError::MissingMethodError("reports".to_string())); + writeln!(io::stderr(), "{}\n", opt.usage()).ok(); + } + } + }, + _ => { + err.issues.push(CLIError::MissingCommandError); + writeln!(io::stderr(), "{}\n", self.opt.usage()).ok(); } } - else if self.opt.cmd_batch_reports { - if self.opt.cmd_list { - call_result = self._batch_reports_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_group_items { - if self.opt.cmd_delete { - call_result = self._group_items_delete(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._group_items_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._group_items_list(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_groups { - if self.opt.cmd_delete { - call_result = self._groups_delete(dry_run, &mut err); - } else if self.opt.cmd_insert { - call_result = self._groups_insert(dry_run, &mut err); - } else if self.opt.cmd_list { - call_result = self._groups_list(dry_run, &mut err); - } else if self.opt.cmd_update { - call_result = self._groups_update(dry_run, &mut err); - } else { - unreachable!(); - } - } - else if self.opt.cmd_reports { - if self.opt.cmd_query { - call_result = self._reports_query(dry_run, &mut err); - } else { - unreachable!(); - } - } else { - unreachable!(); - } if dry_run { if err.issues.len() > 0 { err_opt = Some(err); } + Err(err_opt) + } else { + Ok(call_result) } - (call_result, err_opt) } // Please note that this call will fail if any part of the opt can't be handled - fn new(opt: Options) -> Result<Engine, InvalidOptionsError> { + fn new(opt: ArgMatches<'a, 'n>) -> Result<Engine<'a, 'n>, InvalidOptionsError> { let (config_dir, secret) = { - let config_dir = match cmn::assure_config_dir_exists(&opt.flag_config_dir) { + let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) { Err(e) => return Err(InvalidOptionsError::single(e, 3)), Ok(p) => p, }; @@ -823,7 +863,7 @@ impl Engine { }; let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate, - if opt.flag_debug_auth { + if opt.is_present("debug-auth") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -836,7 +876,7 @@ impl Engine { }, None); let client = - if opt.flag_debug { + if opt.is_present("debug") { hyper::Client::with_connector(mock::TeeConnector { connector: hyper::net::HttpConnector(None) }) @@ -846,37 +886,366 @@ impl Engine { let engine = Engine { opt: opt, hub: api::YouTubeAnalytics::new(client, auth), + gp: vec!["alt", "fields", "key", "oauth-token", "pretty-print", "quota-user", "user-ip"], + gpm: vec![ + ("oauth-token", "oauth_token"), + ("pretty-print", "prettyPrint"), + ("quota-user", "quotaUser"), + ("user-ip", "userIp"), + ] }; match engine._doit(true) { - (_, Some(err)) => Err(err), - _ => Ok(engine), + Err(Some(err)) => Err(err), + Err(None) => Ok(engine), + Ok(_) => unreachable!(), } } - // Execute the call with all the bells and whistles, informing the caller only if there was an error. - // The absense of one indicates success. - fn doit(&self) -> Option<api::Error> { - self._doit(false).0 + fn doit(&self) -> Result<(), DoitError> { + match self._doit(false) { + Ok(res) => res, + Err(_) => unreachable!(), + } } } fn main() { - let opts: Options = Options::docopt().decode().unwrap_or_else(|e| e.exit()); - let debug = opts.flag_debug; - match Engine::new(opts) { + let arg_data = [ + ("batch-report-definitions", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves a list of available batch report definitions."##), + "Details at http://byron.github.io/google-apis-rs/google_youtubeanalytics1_cli/batch-report-definitions_list", + vec![ + (Some(r##"on-behalf-of-content-owner"##), + None, + Some(r##"The onBehalfOfContentOwner parameter identifies the content owner that the user is acting on behalf of."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("batch-reports", "methods: 'list'", vec![ + ("list", + Some(r##"Retrieves a list of processed batch reports."##), + "Details at http://byron.github.io/google-apis-rs/google_youtubeanalytics1_cli/batch-reports_list", + vec![ + (Some(r##"batch-report-definition-id"##), + None, + Some(r##"The batchReportDefinitionId parameter specifies the ID of the batch reportort definition for which you are retrieving reports."##), + Some(true), + Some(false)), + + (Some(r##"on-behalf-of-content-owner"##), + None, + Some(r##"The onBehalfOfContentOwner parameter identifies the content owner that the user is acting on behalf of."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("group-items", "methods: 'delete', 'insert' and 'list'", vec![ + ("delete", + Some(r##"Removes an item from a group."##), + "Details at http://byron.github.io/google-apis-rs/google_youtubeanalytics1_cli/group-items_delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The id parameter specifies the YouTube group item ID for the group that is being deleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("insert", + Some(r##"Creates a group item."##), + "Details at http://byron.github.io/google-apis-rs/google_youtubeanalytics1_cli/group-items_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Returns a collection of group items that match the API request parameters."##), + "Details at http://byron.github.io/google-apis-rs/google_youtubeanalytics1_cli/group-items_list", + vec![ + (Some(r##"group-id"##), + None, + Some(r##"The id parameter specifies the unique ID of the group for which you want to retrieve group items."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("groups", "methods: 'delete', 'insert', 'list' and 'update'", vec![ + ("delete", + Some(r##"Deletes a group."##), + "Details at http://byron.github.io/google-apis-rs/google_youtubeanalytics1_cli/groups_delete", + vec![ + (Some(r##"id"##), + None, + Some(r##"The id parameter specifies the YouTube group ID for the group that is being deleted."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + ]), + ("insert", + Some(r##"Creates a group."##), + "Details at http://byron.github.io/google-apis-rs/google_youtubeanalytics1_cli/groups_insert", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("list", + Some(r##"Returns a collection of groups that match the API request parameters. For example, you can retrieve all groups that the authenticated user owns, or you can retrieve one or more groups by their unique IDs."##), + "Details at http://byron.github.io/google-apis-rs/google_youtubeanalytics1_cli/groups_list", + vec![ + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ("update", + Some(r##"Modifies a group. For example, you could change a group's title."##), + "Details at http://byron.github.io/google-apis-rs/google_youtubeanalytics1_cli/groups_update", + vec![ + (Some(r##"kv"##), + Some(r##"r"##), + Some(r##"Set various fields of the request structure, matching the key=value form"##), + Some(true), + Some(true)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ("reports", "methods: 'query'", vec![ + ("query", + Some(r##"Retrieve your YouTube Analytics reports."##), + "Details at http://byron.github.io/google-apis-rs/google_youtubeanalytics1_cli/reports_query", + vec![ + (Some(r##"ids"##), + None, + Some(r##"Identifies the YouTube channel or content owner for which you are retrieving YouTube Analytics data. + - To request data for a YouTube user, set the ids parameter value to channel==CHANNEL_ID, where CHANNEL_ID specifies the unique YouTube channel ID. + - To request data for a YouTube CMS content owner, set the ids parameter value to contentOwner==OWNER_NAME, where OWNER_NAME is the CMS name of the content owner."##), + Some(true), + Some(false)), + + (Some(r##"start-date"##), + None, + Some(r##"The start date for fetching YouTube Analytics data. The value should be in YYYY-MM-DD format."##), + Some(true), + Some(false)), + + (Some(r##"end-date"##), + None, + Some(r##"The end date for fetching YouTube Analytics data. The value should be in YYYY-MM-DD format."##), + Some(true), + Some(false)), + + (Some(r##"metrics"##), + None, + Some(r##"A comma-separated list of YouTube Analytics metrics, such as views or likes,dislikes. See the Available Reports document for a list of the reports that you can retrieve and the metrics available in each report, and see the Metrics document for definitions of those metrics."##), + Some(true), + Some(false)), + + (Some(r##"v"##), + Some(r##"p"##), + Some(r##"Set various optional parameters, matching the key=value form"##), + Some(false), + Some(true)), + + (Some(r##"out"##), + Some(r##"o"##), + Some(r##"Specify the file into which to write the program's output"##), + Some(false), + Some(false)), + ]), + ]), + + ]; + + let mut app = App::new("youtubeanalytics1") + .author("Sebastian Thiel <byronimo@gmail.com>") + .version("0.2.0+20150304") + .about("Retrieve your YouTube Analytics reports.") + .after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_youtubeanalytics1_cli") + .arg(Arg::with_name("url") + .long("scope") + .help("Specify the authentication a method should be executed in. Each scope requires the user to grant this application permission to use it.If unset, it defaults to the shortest scope url for a particular method.") + .multiple(true) + .takes_value(true)) + .arg(Arg::with_name("folder") + .long("config-dir") + .help("A directory into which we will store our persistent data. Defaults to a user-writable directory that we will create during the first invocation.[default: ~/.google-service-cli") + .multiple(false) + .takes_value(true)) + .arg(Arg::with_name("debug") + .long("debug") + .help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)) + .arg(Arg::with_name("debug-auth") + .long("debug-auth") + .help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.") + .multiple(false) + .takes_value(false)); + + for &(main_command_name, ref about, ref subcommands) in arg_data.iter() { + let mut mcmd = SubCommand::new(main_command_name).about(about); + + for &(sub_command_name, ref desc, url_info, ref args) in subcommands { + let mut scmd = SubCommand::new(sub_command_name); + if let &Some(desc) = desc { + scmd = scmd.about(desc); + } + scmd = scmd.after_help(url_info); + + for &(ref arg_name, ref flag, ref desc, ref required, ref multi) in args { + let arg_name_str = + match (arg_name, flag) { + (&Some(an), _ ) => an, + (_ , &Some(f)) => f, + _ => unreachable!(), + }; + let mut arg = Arg::with_name(arg_name_str); + if let &Some(short_flag) = flag { + arg = arg.short(short_flag); + } + if let &Some(desc) = desc { + arg = arg.help(desc); + } + if arg_name.is_some() && flag.is_some() { + arg = arg.takes_value(true); + } + if let &Some(required) = required { + arg = arg.required(required); + } + if let &Some(multi) = multi { + arg = arg.multiple(multi); + } + scmd = scmd.arg(arg); + } + mcmd = mcmd.subcommand(scmd); + } + app = app.subcommand(mcmd); + } + + let matches = app.get_matches(); + + let debug = matches.is_present("debug"); + match Engine::new(matches) { Err(err) => { - writeln!(io::stderr(), "{}", err).ok(); env::set_exit_status(err.exit_code); + writeln!(io::stderr(), "{}", err).ok(); }, Ok(engine) => { - if let Some(err) = engine.doit() { - if debug { - writeln!(io::stderr(), "{:?}", err).ok(); - } else { - writeln!(io::stderr(), "{}", err).ok(); - } + if let Err(doit_err) = engine.doit() { env::set_exit_status(1); + match doit_err { + DoitError::IoError(path, err) => { + writeln!(io::stderr(), "Failed to open output file '{}': {}", path, err).ok(); + }, + DoitError::ApiError(err) => { + if debug { + writeln!(io::stderr(), "{:?}", err).ok(); + } else { + writeln!(io::stderr(), "{}", err).ok(); + } + } + } } } } diff --git a/gen/youtubeanalytics1/Cargo.toml b/gen/youtubeanalytics1/Cargo.toml index 1a1443f4d1..fefa2918e9 100644 --- a/gen/youtubeanalytics1/Cargo.toml +++ b/gen/youtubeanalytics1/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "google-youtubeanalytics1" -version = "0.1.6+20150304" +version = "0.1.7+20150304" authors = ["Sebastian Thiel <byronimo@gmail.com>"] description = "A complete library to interact with YouTube Analytics (protocol v1)" repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/youtubeanalytics1" @@ -15,9 +15,10 @@ keywords = ["youtubeAnalytics", "google", "protocol", "web", "api"] [dependencies] -hyper = "*" +hyper = ">= 0.4.0" mime = "*" yup-oauth2 = "*" url = "*" serde = ">= 0.3.0" serde_macros = "*" +json-tools = ">= 0.3.0" diff --git a/gen/youtubeanalytics1/README.md b/gen/youtubeanalytics1/README.md index 4fa155c3aa..4c1d30a6ad 100644 --- a/gen/youtubeanalytics1/README.md +++ b/gen/youtubeanalytics1/README.md @@ -5,7 +5,7 @@ DO NOT EDIT ! --> The `google-youtubeanalytics1` library allows access to all features of the *Google YouTube Analytics* service. -This documentation was generated from *YouTube Analytics* crate version *0.1.6+20150304*, where *20150304* is the exact revision of the *youtubeAnalytics:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +This documentation was generated from *YouTube Analytics* crate version *0.1.7+20150304*, where *20150304* is the exact revision of the *youtubeAnalytics:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. Everything else about the *YouTube Analytics* *v1* API can be found at the [official documentation site](http://developers.google.com/youtube/analytics/). @@ -171,7 +171,7 @@ These will always take a single argument, for which the following statements are * [PODs][wiki-pod] are handed by copy * strings are passed as `&str` -* [request values](http://byron.github.io/google-apis-rs/google_youtubeanalytics1/trait.RequestValue.html) are borrowed +* [request values](http://byron.github.io/google-apis-rs/google_youtubeanalytics1/trait.RequestValue.html) are moved Arguments will always be copied or cloned into the builder, to make them independent of their original life times. diff --git a/gen/youtubeanalytics1/src/cmn.rs b/gen/youtubeanalytics1/src/cmn.rs index b7665b194b..908bef39dc 100644 --- a/gen/youtubeanalytics1/src/cmn.rs +++ b/gen/youtubeanalytics1/src/cmn.rs @@ -138,7 +138,7 @@ pub trait Delegate { /// [exponential backoff algorithm](http://en.wikipedia.org/wiki/Exponential_backoff). /// /// Return retry information. - fn http_error(&mut self, &hyper::HttpError) -> Retry { + fn http_error(&mut self, &hyper::Error) -> Retry { Retry::Abort } @@ -173,7 +173,10 @@ pub trait Delegate { /// Called after we have retrieved a new upload URL for a resumable upload to store it /// in case we fail or cancel. That way, we can attempt to resume the upload later, /// see `upload_url()`. - fn store_upload_url(&mut self, url: &str) { + /// It will also be called with None after a successful upload, which allows the delegate + /// to forget the URL. That way, we will not attempt to resume an upload that has already + /// finished. + fn store_upload_url(&mut self, url: Option<&str>) { let _ = url; } @@ -247,7 +250,7 @@ impl Delegate for DefaultDelegate {} #[derive(Debug)] pub enum Error { /// The http connection failed - HttpError(hyper::HttpError), + HttpError(hyper::Error), /// An attempt was made to upload a resource with size stored in field `.0` /// even though the maximum upload size is what is stored in field `.1`. @@ -290,8 +293,20 @@ impl Display for Error { writeln!(f, "The application's API key was not found in the configuration").ok(); writeln!(f, "It is used as there are no Scopes defined for this method.") }, - Error::BadRequest(ref err) - => writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message), + Error::BadRequest(ref err) => { + try!(writeln!(f, "Bad Requst ({}): {}", err.error.code, err.error.message)); + for err in err.error.errors.iter() { + try!(writeln!(f, " {}: {}, {}{}", + err.domain, + err.message, + err.reason, + match &err.location { + &Some(ref loc) => format!("@{}", loc), + &None => String::new(), + })); + } + Ok(()) + }, Error::MissingToken(ref err) => writeln!(f, "Token retrieval failed with error: {}", err), Error::Cancelled => @@ -459,6 +474,16 @@ impl<'a> Read for MultiPartReader<'a> { header!{ #[doc="The `X-Upload-Content-Type` header."] (XUploadContentType, "X-Upload-Content-Type") => [Mime] + + xupload_content_type { + test_header!( + test1, + vec![b"text/plain"], + Some(HeaderField( + vec![Mime(TopLevel::Text, SubLevel::Plain, Vec::new())] + ))); + + } } #[derive(Clone, PartialEq, Debug)] @@ -576,7 +601,7 @@ pub struct ResumableUploadHelper<'a, A: 'a> { impl<'a, A> ResumableUploadHelper<'a, A> where A: oauth2::GetToken { - fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::HttpResult<hyper::client::Response>> { + fn query_transfer_status(&mut self) -> std::result::Result<u64, hyper::Result<hyper::client::Response>> { loop { match self.client.post(self.url) .header(UserAgent(self.user_agent.to_string())) @@ -612,7 +637,7 @@ impl<'a, A> ResumableUploadHelper<'a, A> /// returns None if operation was cancelled by delegate, or the HttpResult. /// It can be that we return the result just because we didn't understand the status code - /// caller should check for status himself before assuming it's OK to use - pub fn upload(&mut self) -> Option<hyper::HttpResult<hyper::client::Response>> { + pub fn upload(&mut self) -> Option<hyper::Result<hyper::client::Response>> { let mut start = match self.start_at { Some(s) => s, None => match self.query_transfer_status() { diff --git a/gen/youtubeanalytics1/src/lib.rs b/gen/youtubeanalytics1/src/lib.rs index 8bb4816340..c4d2cbfcde 100644 --- a/gen/youtubeanalytics1/src/lib.rs +++ b/gen/youtubeanalytics1/src/lib.rs @@ -2,7 +2,7 @@ // This file was generated automatically from 'src/mako/api/lib.rs.mako' // DO NOT EDIT ! -//! This documentation was generated from *YouTube Analytics* crate version *0.1.6+20150304*, where *20150304* is the exact revision of the *youtubeAnalytics:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.6*. +//! This documentation was generated from *YouTube Analytics* crate version *0.1.7+20150304*, where *20150304* is the exact revision of the *youtubeAnalytics:v1* schema built by the [mako](http://www.makotemplates.org/) code generator *v0.1.7*. //! //! Everything else about the *YouTube Analytics* *v1* API can be found at the //! [official documentation site](http://developers.google.com/youtube/analytics/). @@ -172,7 +172,7 @@ //! //! * [PODs][wiki-pod] are handed by copy //! * strings are passed as `&str` -//! * [request values](trait.RequestValue.html) are borrowed +//! * [request values](trait.RequestValue.html) are moved //! //! Arguments will always be copied or cloned into the builder, to make them independent of their original life times. //! @@ -181,7 +181,6 @@ //! [google-go-api]: https://github.com/google/google-api-go-client //! //! -#![feature(std_misc)] // Unused attributes happen thanks to defined, but unused structures // We don't warn about this, as depending on the API, some data structures or facilities are never used. // Instead of pre-determining this, we just disable the lint. It's manually tuned to not have any @@ -197,6 +196,7 @@ extern crate serde; extern crate yup_oauth2 as oauth2; extern crate mime; extern crate url; +extern crate json_tools; mod cmn; @@ -332,7 +332,7 @@ impl<'a, C, A> YouTubeAnalytics<C, A> YouTubeAnalytics { client: RefCell::new(client), auth: RefCell::new(authenticator), - _user_agent: "google-api-rust-client/0.1.6".to_string(), + _user_agent: "google-api-rust-client/0.1.7".to_string(), } } @@ -353,7 +353,7 @@ impl<'a, C, A> YouTubeAnalytics<C, A> } /// Set the user-agent header field to use in all requests to the server. - /// It defaults to `google-api-rust-client/0.1.6`. + /// It defaults to `google-api-rust-client/0.1.7`. /// /// Returns the previously set user-agent. pub fn user_agent(&mut self, agent_name: String) -> String { @@ -1224,7 +1224,7 @@ impl<'a, C, A> ReportQueryCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1246,7 +1246,7 @@ impl<'a, C, A> ReportQueryCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1513,7 +1513,7 @@ impl<'a, C, A> BatchReportDefinitionListCall<'a, C, A> where C: BorrowMut<hyper: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1535,7 +1535,7 @@ impl<'a, C, A> BatchReportDefinitionListCall<'a, C, A> where C: BorrowMut<hyper: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -1705,6 +1705,7 @@ impl<'a, C, A> GroupItemInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, GroupItem)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -1738,11 +1739,20 @@ impl<'a, C, A> GroupItemInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -1765,7 +1775,7 @@ impl<'a, C, A> GroupItemInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -1974,7 +1984,7 @@ impl<'a, C, A> GroupItemListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -1996,7 +2006,7 @@ impl<'a, C, A> GroupItemListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2202,7 +2212,7 @@ impl<'a, C, A> GroupItemDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2224,7 +2234,7 @@ impl<'a, C, A> GroupItemDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2420,7 +2430,7 @@ impl<'a, C, A> GroupDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2442,7 +2452,7 @@ impl<'a, C, A> GroupDeleteCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Delete, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Delete, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -2611,6 +2621,7 @@ impl<'a, C, A> GroupInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Group)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -2644,11 +2655,20 @@ impl<'a, C, A> GroupInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -2671,7 +2691,7 @@ impl<'a, C, A> GroupInsertCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Post, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Post, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -2888,7 +2908,7 @@ impl<'a, C, A> GroupListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -2910,7 +2930,7 @@ impl<'a, C, A> GroupListCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: oau access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()); @@ -3093,6 +3113,7 @@ impl<'a, C, A> GroupUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o /// Perform the operation you have build so far. pub fn doit(mut self) -> Result<(hyper::client::Response, Group)> { + use json_tools::{TokenReader, Lexer, BufferType, TokenType, FilterTypedKeyValuePairs, IteratorExt}; use std::io::{Read, Seek}; use hyper::header::{ContentType, ContentLength, Authorization, UserAgent, Location}; let mut dd = DefaultDelegate; @@ -3126,11 +3147,20 @@ impl<'a, C, A> GroupUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } let mut json_mime_type = mime::Mime(mime::TopLevel::Application, mime::SubLevel::Json, Default::default()); - let mut request_value_reader = io::Cursor::new(json::to_vec(&self._request)); + let mut request_value_reader = + { + let json_cache = json::to_string(&self._request).unwrap(); + let mut mem_dst = io::Cursor::new(Vec::with_capacity(json_cache.len())); + io::copy(&mut Lexer::new(json_cache.bytes(), BufferType::Span) + .filter_key_value_by_type(TokenType::Null) + .reader(Some(&json_cache)), &mut mem_dst).unwrap(); + mem_dst.seek(io::SeekFrom::Start(0)).unwrap(); + mem_dst + }; let request_size = request_value_reader.seek(io::SeekFrom::End(0)).unwrap(); request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); @@ -3153,7 +3183,7 @@ impl<'a, C, A> GroupUpdateCall<'a, C, A> where C: BorrowMut<hyper::Client>, A: o request_value_reader.seek(io::SeekFrom::Start(0)).unwrap(); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Put, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Put, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone()) .header(ContentType(json_mime_type.clone())) @@ -3359,7 +3389,7 @@ impl<'a, C, A> BatchReportListCall<'a, C, A> where C: BorrowMut<hyper::Client>, if params.len() > 0 { url.push('?'); - url.push_str(&url::form_urlencoded::serialize(params.iter().map(|t| (t.0, t.1.as_ref())))); + url.push_str(&url::form_urlencoded::serialize(params)); } @@ -3381,7 +3411,7 @@ impl<'a, C, A> BatchReportListCall<'a, C, A> where C: BorrowMut<hyper::Client>, access_token: token.access_token }); let mut req_result = { let mut client = &mut *self.hub.client.borrow_mut(); - let mut req = client.borrow_mut().request(hyper::method::Method::Get, url.as_ref()) + let mut req = client.borrow_mut().request(hyper::method::Method::Get, &url) .header(UserAgent(self.hub._user_agent.clone())) .header(auth_header.clone());